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(
)print
('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(
)print
('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(
)print
('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(
)print
('multithread took %.3f seconds'
%(end - start)
)if __name__ ==
"__main__"
: n =
5 test_io(n)
test_io_thread(n)
**輸出:
took 5.179 seconds
multithread took 1.451 seconds
可以看到單執行緒花費時間與多執行緒花費時間之比接近1:4,考慮執行緒排程的時間,這個跟一般語言的多線
程起的作用比較相似。這是因為當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...