python多執行緒————4、執行緒同步之Lock,RLock
阿新 • • 發佈:2018-11-12
在多執行緒同時請求同一個資源並進行修改時可能會造成結果出錯,例如共享變數
from dis import dis import threading a = 0 def add(): global a a += 1 def desc(): global a a -= 1 print(dis(add)) print(dis(desc)) thread_add = threading.Thread(target=add) thread_desc = threading.Thread(target=desc) thread_add.start() thread_desc.start() thread_add.join() thread_desc.join() print(a)
在上面的程式碼中存在一個什麼問題呢?雖然執行沒能看出什麼問題,看dis這個模組打印出的內容,一個+=運算是先load a 然後load 1 然後做運算再把結果賦值給a。那問題來了如果a同時被desc和add 載入呢,那desc和add載入進去的a值都為0,那a做add和desc運算後結果可能為1 或者-1而不是0。
0 LOAD_GLOBAL 0 (a)
2 LOAD_CONST 1 (1)
4 INPLACE_ADD
6 STORE_GLOBAL 0 (a)
8 LOAD_CONST 0 (None)
要怎麼解決這個同步問題呢,解決方法是給資源加把鎖Lock,RLock(可重如的鎖)
from threading import Lock total = 0 lock = Lock() def add(): global total global lock #1.do something1 #2. io操作 #3.do someting3 for i in range(1000000): lock.acquire() total += 1 lock.release() def desc(): global total global lock for i in range(1000000): lock.acquire() total -= 1 lock.release() import threading thread1 = threading.Thread(target=add) thread2 = threading.Thread(target=desc) thread1.start() thread2.start() thread1.join() thread2.join() print(total) print(dis(add))
Lock在使用過程中不可以重入,重入會造成死鎖,比如
lock.acquire()
lock.acquire()
而CLock是在同一執行緒中是可以重入的,但要記得釋放相同數量的鎖。