Gil全局解釋鎖延伸擴(kuò)展
作用 : 保證同一時(shí)刻只有一個(gè)線程能使用到cpu
解釋 : 當(dāng)我們使用多線程的時(shí)候,在一個(gè)進(jìn)程中只有一個(gè)GIL鎖,那么這多個(gè)線程中誰拿到GIL誰就可以使用cpu(ps:多個(gè)進(jìn)程有多個(gè)Gil鎖)
問題1: 什么時(shí)候會(huì)釋放Gil鎖,
答: ?1.遇到像 i/o操作這種 會(huì)有時(shí)間空閑情況 造成cpu閑置的情況會(huì)釋放Gil
? ? ? 2會(huì)有一個(gè)專門ticks進(jìn)行計(jì)數(shù) 一旦ticks數(shù)值達(dá)到100這個(gè)時(shí)候釋放Gil鎖 線程之間開始競爭Gil鎖(說明:ticks這個(gè)數(shù)值可以進(jìn)行設(shè)置來延長或者縮減獲得Gil鎖的線程使用cpu的時(shí)間)
問題2: 互斥鎖和Gil鎖的關(guān)系
Gil鎖? :保證同一時(shí)刻只有一個(gè)線程能使用到cpu
互斥鎖 : 多線程時(shí),保證修改共享數(shù)據(jù)時(shí)有序的修改,不會(huì)產(chǎn)生數(shù)據(jù)修改混亂
首先假設(shè)只有一個(gè)進(jìn)程,這個(gè)進(jìn)程中有兩個(gè)線程 Thread1,Thread2, 要修改共享的數(shù)據(jù)data, 并且有互斥鎖
執(zhí)行以下步驟
(1)多線程運(yùn)行,假設(shè)Thread1獲得GIL可以使用cpu,這時(shí)Thread1獲得 互斥鎖lock,Thread1可以改date數(shù)據(jù)(但并沒有開始修改數(shù)據(jù))
(2)Thread1線程在修改date數(shù)據(jù)前發(fā)生了 i/o操作 或者 ticks計(jì)數(shù)滿100
(注意就是沒有運(yùn)行到修改data數(shù)據(jù)),這個(gè)時(shí)候 Thread1 讓出了Gil,Gil鎖可以被競爭
(3) Thread1 和 Thread2 開始競爭Gil (注意:如果Thread1是因?yàn)閕/o 阻塞 讓出的Gil Thread2必定拿到Gil,如果Thread1是因?yàn)閠icks計(jì)數(shù)滿100讓出Gil這個(gè)時(shí)候Thread1 和 Thread2 公平競爭)
(4)假設(shè) Thread2正好獲得了GIL, 運(yùn)行代碼去修改共享數(shù)據(jù)date,由于Thread1有互斥鎖lock,所以Thread2無法更改共享數(shù)據(jù)date,這時(shí)Thread2讓出Gil鎖, GIL鎖再次發(fā)生競爭
(5)假設(shè)Thread1又搶到GIL,由于其有互斥鎖Lock所以其可以繼續(xù)修改共享數(shù)據(jù)data,當(dāng)Thread1修改完數(shù)據(jù)釋放互斥鎖lock,Thread2在獲得GIL與lock后才可對data進(jìn)行修改
以上描述了 互斥鎖和Gil鎖的 一個(gè)關(guān)系
總結(jié):
1.線程鎖是fine-grained(細(xì)粒度)的鎖,程序員需要自行加/解鎖來保證線程安全;
2.全局解釋鎖是coarse-grained(粗粒度)的鎖,語言層面本身維護(hù)著一個(gè)全局的鎖機(jī)制用來保證線程安全;
前一種方式比較典型的是 Java, Jython 等, 后一種方式比較典型的是 CPython (即Python)。
所以,線程互斥鎖和全局解釋鎖的關(guān)系,前一個(gè)是程序自定義的線程鎖,后一個(gè)是CPython強(qiáng)加給解釋器的全局線程鎖,從本質(zhì)上來講,兩者并沒有太大區(qū)別,都是為了線程安全而設(shè)計(jì)的,只是GIL比較惡心,沒法移除,并強(qiáng)行執(zhí)行,導(dǎo)致python的多線程成為偽并發(fā)的多線程,每一時(shí)刻,python一個(gè)進(jìn)程下有且只有一個(gè)線程能獲取到GIL鎖執(zhí)行任務(wù)。