併發程式設計是我們程式設計中常用的優化程式效能的手段,能提高cpu的使用率。一般使用是多執行緒,多程序,協程
一、python的全域性解釋鎖gil
我們目前跑的python程式大多數都是在cpython上執行的。cpython是有乙個全域性解釋鎖,具體什麼意思,可以兩個方面理解
在同一時刻,只能執行乙個執行緒
無法將多個執行緒對映到多個cpu上執行
也就是說python多執行緒是有一定侷限性的,對於io密集型的任務,我們可以很好的利用多執行緒,對於計算密集型的任務,多執行緒就沒有意義了,只能利用多程序提高效能
二、簡單多執行緒程式設計
第一種形式:使用threading庫,直接使用thread類
fromthreading import thread
import time
def fun(n):
#dosomething
time.sleep(n)
print(n)
t1= thread(target=fun, args=(1,))
t2= thread(target=fun, args=(2,))
# 啟動執行緒
t1.start()
t2.start()
# 等待執行緒結束
t1.join()
t2.join()
第二種形式:使用threading庫,繼承thread類
fromthreading import thread
import timeclassmythread(thread):
def __init__(self, n):
self.n=n
super().__init__()
def run(self):
time.sleep(self.n)
print(self.n)
t1= mythread(1)
t2= mythread(2)
t1.start()
t2.start()
t1.join()
t2.join()
三、執行緒安全
多個執行緒在同乙個程序中執行時,是共享記憶體空間的,這就有可能引起乙個執行緒在修改乙個變數到一半的時候去休息了,回來的時候發現這個變數變了,這就會產生問題
如何保證執行緒安全,一般有下面幾個方法
使用私有變數,每個執行緒都只知道自己的變數,其他執行緒無法修改,一般通過區域性變數實現
通過拷貝資料到自己的空間,自己修改自己拷貝的資料,這樣不會影響其他執行緒,一般通過thread.local實現
控制共享變數的訪問方式,同一時刻只能有乙個執行緒修改,一般通過加鎖實現
還有一些其他方法保證執行緒安全,不同的場景,保證執行緒安全的方法也不同,需要合理採用。下面用**說明一下
首先,我們不加鎖,有兩個執行緒共同操作乙個共享變數
# 沒有使用鎖的情況fromthreading import thread
n= 0def add():globalnfor i in range(1000000):
n+= 1def sub():globalnfor i in range(1000000):
n-= 1t1= thread(target=add)
t2= thread(target=sub)
t1.start()
t2.start()
t1.join()
t2.join()
print(n)
輸出的結果,發現不是我們想象中的0,這就是因為兩個執行緒執行期間,乙個執行緒把 對n的操作執行到一半時候,去休息了,回來繼續執行剩下一半的過程中,另乙個執行緒修改了n,這樣就造成了執行緒不安全的問題,最後的結果不一致。
加鎖後的**
fromthreading import thread, lock
n= 0
lock =lock()
def add(lock):globalnfor i in range(1000000):lock.acquire()
n+= 1
lock.release()
def sub(lock):globalnfor i in range(1000000):lock.acquire()
n-= 1
lock.release()
t1= thread(target=add, args=(lock,))
t2= thread(target=sub, args=(lock,))
t1.start()
t2.start()
t1.join()
t2.join()
print(n)
這次輸出的結果都是0了,我們在整個修改共享變數的過程中,加了鎖,在鎖未釋放的時候,其他執行緒是執行不了的
四、執行緒間通訊
執行緒間通訊最常用的是佇列,python提供了乙個執行緒安全的佇列,from queue import queue,在多個執行緒之間操作佇列裡的元素都是安全的
還有更加複雜的執行緒通訊機制,比如條件變數,訊號量等,python也提供了相應的模組
五、執行緒池
有時候,我們有很多條資料,我們希望同一時刻總共有5個執行緒來處理這一批資料,乙個執行緒結束後,再啟動另乙個執行緒,總數不能超過5個,這時候執行緒池就可以很好的解決我們的問題了
fromconcurrent.futures.thread import threadpoolexecutorfromconcurrent.futures import wait
import time
pools= threadpoolexecutor(5)
data= list(range(20))
res=
def fun(n):
time.sleep(2)
print(n)returnnfor n indata:
# 等待所有執行緒執行完畢
wait(res)
執行緒池還給我們提供了更多的功能,我們可以獲取執行緒返回的結果
fromconcurrent.futures.thread import threadpoolexecutorfromconcurrent.futures import as_completed
import time
pools= threadpoolexecutor(5)
data= list(range(20))
res=
def fun(n):
time.sleep(2)returnnfor n indata:
# 獲取執行緒結束後的結果for r inas_completed(res):
print(r.result())
六、多程序程式設計
關於python多程序,在大多數業務開發中,用的比較少,我只給出乙個簡單的例子(實際上程序在執行的時候比這個負責,是會拷貝乙份父程序的資訊的)
frommultiprocessing import process
import time
def fun(n):
#dosomething
time.sleep(n)
print(n)if __name__ == "__main__":
p1= process(target=fun, args=(1,))
p2= process(target=fun, args=(2,))
p1.start()
p2.start()
p1.join()
p2.join()
七、總結
併發程式設計是我們提高程式效能的常用手段,一般來說就是多執行緒,多程序,協程,併發程式設計的時候,我們還有許多問題需要考慮,執行緒安全,通訊等等。
Spring Cloud 併發調優
測試介面 登入 鏈路呼叫 nginx zuul server servicea,serviceb,servicec,serviced 因為登入介面牽涉到一系列的加密校驗 許可權角色 賬號密碼驗證,所以 zuul server 路由之後,會呼叫很多個微服務來獲取使用者資訊。伺服器的話都是用docker...
多執行緒高併發調優
1.首先理解幾個多執行緒的概念 1 執行緒安全 保證執行緒的排程順序不變,以免引起資料不一致問題 2 執行緒同步 幾個執行緒協調同步,當幾個執行緒共享同乙份資源時,調整執行順序,當前乙個執行緒完成時,再執行下乙個 3 何為高併發 指程式在短時間內集中處理大量操作的情況,現實場景如 秒殺活動,搶票活動...
CPU調優併發問題
多核cpu 讓指定的程式 在指定的cpu上執行 看的是程序型別 cpu消耗型 i o消耗型 多執行緒併發 乙個程式執行 我使用到兩個cpu核心 我們可以讓改程式以執行緒方式執行 每 個核心執行乙個執行緒 多核情況下以執行緒方式執行效果更好一些,單核的話區別就不大了 測試 io消耗型 bin bash...