自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Python主線程問(wèn)題進(jìn)行研究討論

開(kāi)發(fā) 后端
Python主線程具有非常簡(jiǎn)捷而清晰的語(yǔ)法特點(diǎn),適合完成各種高層任務(wù),幾乎可以在所有的操作系統(tǒng)中運(yùn)行。

Python主線程的問(wèn)題這里我想在重申一下,對(duì)于那些從來(lái)沒(méi)有學(xué)習(xí)過(guò)編程或者并非計(jì)算機(jī)專(zhuān)業(yè)的編程學(xué)習(xí)者而言,Python是***的選擇之一,下面文章進(jìn)行學(xué)習(xí)介紹。

PyThread_acquire_lock有兩種工作方式,通過(guò)函數(shù)參數(shù)waitflag來(lái)區(qū)分。這個(gè)waitflag指示當(dāng)GIL當(dāng)前不可獲得時(shí)。是否進(jìn)行等待,更直接地說(shuō),就是當(dāng)前線程是否通過(guò)WaitForSingleObject將自身掛起,直到別的線程釋放GIL,然后由操作系統(tǒng)將自己?jiǎn)拘选?/P>

如果waitflag為0,Python會(huì)檢查當(dāng)前GIL是否可用,GIL中的owned是指示GIL是否可用的變量,在前面的InitializeNonRecursiveMutex中我們看到這個(gè)值被初始化為-1。Python會(huì)檢查這個(gè)值是否為-1,如果是,則意味著GIL可用,必須將其置為0,當(dāng)owned為0后,表示該GIL已經(jīng)被一個(gè)線程占用,不再可用。

對(duì)于我們這里分析的調(diào)用PyEval_InitThread的主線程而言,由于在初始化GIL之后就調(diào)用PyThread_ acquire_lock申請(qǐng)GIL,到這時(shí),并沒(méi)有第二個(gè)線程被創(chuàng)建,所以主線程會(huì)輕而易舉地獲得GIL的使用權(quán)。

注意這里的檢查和更新owned的操作是通過(guò)一個(gè)Win32的系統(tǒng)API——Interlocked- CompareExchange——來(lái)完成的。這個(gè)API是一個(gè)原子操作,其函數(shù)原形和功能如下。原形:InterlockedCompareExchange(PLONG dest, long exchange, long compared) 功能:如果*dest == compared,那么*dest = exchange

與InterlockedCompareExchange相同的,InterlockedIncrement也是一個(gè)原子操作,其功能是將mutex->owned的值增加1。從這里可以看到,當(dāng)一個(gè)線程開(kāi)始等待GIL時(shí),其owned就會(huì)被增加1。顯然我們可以猜測(cè),當(dāng)一個(gè)線程最終釋放GIL時(shí)。

一定會(huì)將GIL的owned減1,這樣當(dāng)所有需要GIL的線程都最終釋放了GIL之后,owned會(huì)再次變?yōu)?1,意味著GIL再次變?yōu)榭捎?。為了清晰地展示這一點(diǎn),我們現(xiàn)在就來(lái)看看PyThread_aquire_lock的逆運(yùn)算,PyThread_release_lock每一個(gè)將從運(yùn)行轉(zhuǎn)態(tài)轉(zhuǎn)為等待狀態(tài)的線程都會(huì)在被掛起之前調(diào)用它以釋放對(duì)GIL的占有。

最終,一個(gè)線程在釋放GIL時(shí),會(huì)通過(guò)SetEvent通知所有在等待GIL的hevent這個(gè)Event內(nèi)核對(duì)象的線程,結(jié)合前面的分析。如果這時(shí)候有線程在等待GIL的hevent,那么將被操作系統(tǒng)喚醒。這就是我們?cè)谇懊娼榻B的Python將線程調(diào)度的第二個(gè)難題委托給操作系統(tǒng)來(lái)實(shí)現(xiàn)的機(jī)制。

到了這時(shí),調(diào)用PyEval_InitThread的線程(也就是Python主線程)已經(jīng)成功獲得了GIL,***會(huì)調(diào)用PyThread_get_thread_ident()。通過(guò)Win32的API:GetCurrent- ThreadId,獲得當(dāng)前Python主線程的id,并將其賦給main_thread,main_thread是一個(gè)靜態(tài)全局變量,專(zhuān)職存儲(chǔ)Python主線程的線程id,用以判斷一個(gè)線程是否是Python主線程。

值得注意的是,obj.done是一個(gè)Win32下的Semaphore內(nèi)核對(duì)象,這個(gè)特殊的內(nèi)核對(duì)象的用途我們馬上就會(huì)看到。我們創(chuàng)建線程的工作需要func和arg,但是Win32下創(chuàng)建線程的API只允許用戶指定一個(gè)自定義的參數(shù),這就是需要用obj來(lái)打包的原因。

完成打包之后,調(diào)用Win32下創(chuàng)建thread的API:_beginthread來(lái)完成線程的創(chuàng)建。奇怪的是,我們期望的線程過(guò)程應(yīng)該是thread1.py中定義的那個(gè)threadPoc呀,而這里指定的線程過(guò)程卻是一個(gè)相當(dāng)面生的bootstrap。實(shí)際上,在bootstrap中,會(huì)最終調(diào)用thread1.py中定義的threadProc。

現(xiàn)在我們來(lái)理清一下Python當(dāng)前的狀態(tài)。Python主線程當(dāng)前實(shí)際上由兩個(gè)Win32下的原生thread構(gòu)成,一個(gè)是執(zhí)行python程序(python.exe)時(shí)操作系統(tǒng)創(chuàng)建的主線程,另一個(gè)是我們通過(guò)thread1.py創(chuàng)建的子線程。

主線程在執(zhí)行PyEval_InitThread的過(guò)程中,獲得了GIL,但是目前已經(jīng)被掛起,這是為了等待子線程中控制著的obj.done。子線程的線程過(guò)程是bootstrap,不過(guò)我們剛才已經(jīng)猜測(cè)了。

從bootstrap出發(fā),最終將在Python解釋器中執(zhí)行python1.py中定義的theadProc。但是,我們知道,子線程為了訪問(wèn)Python解釋器,必須首先獲得GIL,這是Python世界的游戲規(guī)則,誰(shuí)也不能例外。所以,為了避免死鎖,子線程一定會(huì)在申請(qǐng)GIL之前通知obj.done。

【編輯推薦】

  1. 有關(guān)Python系統(tǒng)文件進(jìn)行介紹指導(dǎo)
  2. 如何正確的使用Python函數(shù)
  3. 對(duì)Python 構(gòu)建工具進(jìn)行詳細(xì)介紹分析
  4. PythonAndroid淺析Python優(yōu)勢(shì)所在
  5. 如何使用Python模塊解析配置文件?
責(zé)任編輯:chenqingxiang 來(lái)源: CSDN
相關(guān)推薦

2009-12-24 16:36:27

ADO Connect

2009-12-24 14:54:25

ADO.NET使用

2009-12-28 14:23:37

ADO啟動(dòng)連接

2009-12-24 16:56:21

ADO.NET庫(kù)

2010-02-26 15:43:02

Python線程

2009-12-15 10:24:32

Visio 2008架

2010-02-02 16:47:12

Python主線程

2010-02-01 17:33:24

Python主線程

2009-11-27 09:24:29

VS2003命令

2009-12-24 17:01:42

ADO3.0

2009-11-25 17:01:33

VS2005圖片

2010-03-02 10:36:05

Android窗體

2010-03-10 19:34:45

Python主線程

2024-09-25 13:16:57

2010-02-23 17:35:46

Python

2010-03-01 13:28:44

Python子線程

2010-02-24 11:19:00

Python主線程

2020-07-09 09:55:40

機(jī)器人人工智能系統(tǒng)

2015-08-07 10:40:31

UI主線程

2010-02-22 15:13:01

Python模塊
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)