線程鎖(互斥鎖Mutex)及遞歸鎖


一、線程鎖(互斥鎖)
在一個程序內,主進程可以啟動很多個線程,這些線程都可以訪問主進程的內存空間,在Python中雖然有了GIL,同一時間只有一個線程在運行,可是這些線程的調度都歸系統,操作系統有自身的調度規則,所以就可能造成,
  • 假設兩個線程都在訪問 global count= 0, 每個進程都會執行 count +=1 。(1)(2)(3)第一個線程申請GIL然后,讀取global count到及進程到 cpu ,(4)然后cpu執行到一半,(5)把這個線程停了,將上下文保存到自身寄存器中。注意這時候沒返回結果。這時候解釋器就會把GIL釋放,
  • (6)(7)(8)第二個線程申請GIL執行如上步驟,讀取count= 0 ,cpu計算結束后將結果count=1 返回,(10)(11)解釋器拿到結果進行賦值,此時count=1,這個進程運行結束,(12)(13)然后cpu從寄存器中第一個線程的執行狀態,繼續執行,注意這個讀取的是寄存器中的上下文,就是第一次執行時 count= 0,及第一個線程的上下文。計算結果返回count =1 返回。就造成了結果的錯誤。

1.1 python中的線程鎖(互斥鎖mutex)
使用threading模塊中的Lock類,得到一個全局鎖實例。然后 Lock()實例下 有一個 acquire 方法為加鎖, release 方法釋放鎖
import threading

count = 0
lock = threading.Lock() #申請一個鎖

def count_():
    global count #聲明為全局變量
    lock.acquire()  #加鎖,鎖釋放前不予許其他程序執行
    count += 1
    lock.release()  #執行完 ,釋放鎖


thread_list = []
for i in range(10):
    t = threading.Thread(target= count_)
    t.start()
    thread_list.append(t)

for t in thread_list:
    t.join() #主程序等待所有程序執行完畢

print('Count:{: ^4}'.format(count))
1.2 遞歸鎖
基本用不上,主要目的就是防止鎖里面加鎖,然后程序無法解鎖退出。
import threading,time
 
def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num +=1
    lock.release()
    return num
def run2():
    print("grab the second part data")
    lock.acquire()
    global  num2
    num2+=1
    lock.release()
    return num2
def run3():
    lock.acquire()
    res = run1()
    print('--------between run1 and run2-----')
    res2 = run2()
    lock.release()
    print(res,res2)
 
 
if __name__ == '__main__':
 
    num,num2 = 0,0
    lock = threading.RLock()
    for i in range(10):
        t = threading.Thread(target=run3)
        t.start()
 
while threading.active_count() != 1:
    print(threading.active_count())
else:
    print('----all threads done---')
    print(num,num2)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM