python的標準實現是cpython。
cpython執行python**分為2個步驟:首先,將文字原始碼解釋編譯為位元組碼,然後再用乙個直譯器去
解釋執行位元組碼。位元組碼直譯器是有狀態的,需要維護該狀態的一致性,因此使用了gil(global
interpreter lock,全域性直譯器鎖)。
gil的存在,使得cpython在執行多執行緒**的時候,同一時刻只有乙個執行緒在執行,無法利用多cpu
提高運算效率。但是這個特點也帶來了乙個好處:cpython執行多執行緒的時候,內部物件預設就是執行緒
安全的。這個特性,被非常多的python庫開發者所依賴,直到cpython的開發者想要去除gil的時候,
發現已經有大量的**庫重度依賴這個gil帶來的內部物件預設就是執行緒安全的特性,變成乙個無法解
決的問題了。
雖然多執行緒在平行計算場景下無法帶來好處,但是在阻塞式io場景下,卻仍然可以起到提高效率的作
用。這是因為阻塞式io場景下,執行緒在執行io操作時並不需要占用cpu時間,此時阻塞io的執行緒可以被
掛起的同時繼續執行io操作,而讓出cpu時間給其他執行緒執行非io操作。這樣一來,多執行緒並行io操作
就可以起到提高執行效率的作用了。
綜上,python的標準實現cpython,由於gil的存在,同乙個時刻只能執行乙個執行緒,無法充分利用多
cpu提公升運算效率,因此python的多執行緒適用於阻塞式io的場景,不適用於平行計算的場景。
下面舉乙個對計算量有要求的求乙個數的因數分解的**例項,來說明python多執行緒不適用於並行計
算的場景:
**輸出:# -*- coding:utf-8 -*-
from time import time
from threading import thread
deffactorize
(number)
:for i in
range(1
, number +1)
:if number % i ==0:
yield i
class
factorizethread
(thread)
:def
__init__
(self, number)
: thread.__init__(self)
self.number = number
defrun(self)
: self.factors =
list
(factorize(self.number)
)def
test
(numbers)
: start = time(
)for number in numbers:
list
(factorize(number)
) end = time(
('took %.3f seconds'
%(end - start)
)def
test_thread
(numbers)
: start = time(
) threads =
for number in numbers:
thread = factorizethread(number)
thread.start(
)for t in threads:
t.join(
) end = time(
('mutilthread took %.3f seconds'
%(end - start)
)if __name__ ==
"__main__"
: numbers =
[2139079
,1214759
,1516637
,1852285
] test(numbers)
test_thread(numbers)
以上**執行結果只是乙個參考值,具體資料跟執行環境相關。但是可以看到單執行緒方式比多執行緒方式took 0.319 seconds
mutilthread took 0.539 seconds
的計算速度要快。由於cpython執行多執行緒**時因為gil的原因導致每個時刻只有乙個執行緒在執行,
因此多執行緒平行計算並不能帶來時間上的收益,反而因為排程執行緒而導致總時間花費更長。
對於io阻塞式場景,多執行緒的作用在於發生io阻塞操作時可以排程其他執行緒執行非io操作,因此在這個
場景下,多執行緒是可以節省時間的。可以用以下的**來驗證:
**輸出:# -*- coding:utf-8 -*-
from time import time
from threading import thread
import os
defslow_systemcall
(n):
for x in
range
(100):
open
("test_%s"
% n,
"a")
.write(os.urandom(10)
*100000
)def
test_io
(n):
start = time(
)for _ in
range
(n):
slow_systemcall(_)
end = time(
('took %.3f seconds'
%(end - start)
)def
test_io_thread
(n):
start = time(
) threads =
for _ in
range
(n):
thread = thread(target=slow_systemcall, args=
("t_%s"
%_,)
) thread.start(
)for thread in threads:
thread.join(
) end = time(
('multithread took %.3f seconds'
%(end - start)
)if __name__ ==
"__main__"
: n =
5 test_io(n)
test_io_thread(n)
可以看到單執行緒花費時間與多執行緒花費時間之比接近1:4,考慮執行緒排程的時間,這個跟一般語言的多線took 5.179 seconds
multithread took 1.451 seconds
程起的作用比較相似。這是因為當python執行io操作時,實際上是執行了系統呼叫,此時執行緒會釋放
gil,直到系統呼叫結束時,再申請獲取gil,也就是在io操作期間,執行緒確實是並行執行的。
python的另外乙個實現jpython就沒有gil,但是它並不是最常見的python實現。
rewrite場景例項(適用於開發)
需求 使用者訪問course 11 22 33.html實際上真實訪問是 course 11 22 33 course 33.html root web01 conf.d cat url.oldxu.com.conf server rewrite中的flag 跳轉 redirect 302 臨時跳轉...
QZXing不適用於C 11語法?
重新整理寫過的程式,發現了乙個詭異的問題。將使用了qzxing的源程式包移動到另乙個資料夾後,build,qzxing中的某個檔案出現錯誤。一步步回溯問題可能出現的地方。發現這個程式最開始的版本中並沒有需要c 11支援的語法 如lambda表示式 因此.pro檔案中也沒有config c 11這一句...
extjs和jquery各適用於什麼場景
比較點 extjs jquery 是否收費 extjs3版本開始對於商業用途是實行收費的 開源免費 庫檔案大小 500kb 20kb 是否有及css要載入是否 支援ui 豐富的ui 要使用外掛程式 是否支援物件導向程式設計 支援 復用性強 不支援粒度 extjs是基於元件級 jquery主要是簡化d...