1. 程式人生 > >python多執行緒————4、執行緒同步之Lock,RLock

python多執行緒————4、執行緒同步之Lock,RLock

     在多執行緒同時請求同一個資源並進行修改時可能會造成結果出錯,例如共享變數

     

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是在同一執行緒中是可以重入的,但要記得釋放相同數量的鎖。