48_併發編程-線程-資源共享/鎖

1、數據共享
 
  多個線程內部有本身的數據棧,數據不共享;全局變量在多個線程之間是共享的。
 1 # 線程數據共享不安全加鎖
 2 
 3 import time  4 from threading import Thread, Lock  5 
 6 
 7 num = 100
 8 
 9 def func(t_lock): 10     global num 11  t_lock.acquire() 12     mid = num 13     mid -= 1
14     time.sleep(0.01) # 設置一個時間,模擬數據修改時,先從內存中拿出做修改,在把結果放回去的時間差
15     num = mid 16  t_lock.release() 17 
18 if __name__ == '__main__': 19 
20     t_lock = Lock() 21 
22     t_lst = [] 23     for i in range(10): 24         t_thread = Thread(target=func, args=(t_lock,)) 25  t_lst.append(t_thread) 26  t_thread.start() 27     [t_obj.join() for t_obj in t_lst]    #必須加join,由於主線程和子線程不必定誰快,通常都是主線程快一些,全部咱們要等子線程執行完畢才能看出效果 
28 
29     print('主線程結束!', num)    # 結果爲90
數據共享實例
 
2、同步鎖(互斥鎖) - 產生死鎖
 
  進程也有死鎖與遞歸鎖,在進程那裏忘記說了,放到這裏一切說了額,進程的死鎖和線程的是同樣的,並且通常狀況下進程之間是數據不共享的,不須要加鎖,因爲線程是對全局的數據共享的,因此對於全局的數據進行操做的時候,要加鎖。
  死鎖: 是指兩個或兩個以上的進程或線程在執行過程當中,因爭奪資源而形成的一種互相等待的現象,若無外力做用,它們都將沒法推動下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱爲死鎖進程,以下就是死鎖
 
 1 from threading import Thread,Lock  2 import time  3 
 4 class MyThread(Thread):  5     def run(self):  6  self.func1()  7  self.func2()  8     def func1(self):  9  mutexA.acquire() 10         print('\033[41m%s 拿到A鎖>>>\033[0m' %self.name) 11  mutexB.acquire() 12         print('\033[42m%s 拿到B鎖>>>\033[0m' %self.name) 13  mutexB.release() 14  mutexA.release() 15 
16     def func2(self): 17  mutexB.acquire() 18         print('\033[43m%s 拿到B鎖???\033[0m' %self.name) 19         time.sleep(2) 20 #分析:當線程1執行完func1,而後執行到這裏的時候,拿到了B鎖,線程2執行func1的時候拿到了A鎖,那麼線程2還要繼續執行func1裏面的代碼,再去拿B鎖的時候,發現B鎖被人拿了,那麼就一直等着別人把B鎖釋放,那麼就一直等着,等到線程1的sleep時間用完以後,線程1繼續執行func2,須要拿A鎖了,可是A鎖被線程2拿着呢,尚未釋放,由於他在等着B鎖被釋放,那麼這倆人就尷尬了,你拿着個人老A,我拿着你的B,這就尷尬了,倆人就停在了原地
21         
22  mutexA.acquire() 23         print('\033[44m%s 拿到A鎖???\033[0m' %self.name) 24  mutexA.release() 25  mutexB.release() 26 
27 if __name__ == '__main__': 28 
29     mutexA=Lock()    # 同步鎖必須這樣建立
30     mutexB=Lock() 31     for i in range(10): 32         t=MyThread() 33  t.start() 34 
35 '''
36 Thread-1 拿到A鎖>>> 37 Thread-1 拿到B鎖>>> 38 Thread-1 拿到B鎖??? 39 Thread-2 拿到A鎖>>> 40 而後就卡住,死鎖了 41 '''
死鎖現象

 
3、解決死鎖方案 - 遞歸鎖
 
  解決方法,遞歸鎖,在Python中爲了支持在同一線程中屢次請求同一資源,python提供了可重入鎖RLock。
  這個RLock內部維護着一個Lock和一個counter變量,counter記錄了acquire的次數,從而使得資源能夠被屢次require。直到一個線程全部的acquire都被release,其餘的線程才能得到資源。上面的例子若是使用RLock代替Lock,則不會發生死鎖:
 
 1 import time  2 from threading import Thread,RLock  3 
 4 
 5 class MyThread(Thread):  6 
 7     def __init__(self, lockA, lockB):  8         super().__init__()  9         self.lockA = lockA 10         self.lockB = lockB 11     def run(self): 12  self.func1() 13  self.func2() 14 
15     def func1(self): 16  self.lockA.acquire() 17         print('我是func1') 18  self.lockB.acquire() 19         print('func1中有其餘事') 20  self.lockB.release() 21  self.lockA.release() 22 
23     def func2(self): 24  self.lockB.acquire() 25         print('我是func2') 26         time.sleep(0.5) 27  self.lockA.acquire() 28         print('func2中有什麼事') 29  self.lockA.release() 30  self.lockB.release() 31 
32 if __name__ == '__main__': 33 
34     lockA = lockB = RLock() 35 
36     t1 = MyThread(lockA, lockB) 37  t1.start() 38     t2 = MyThread(lockA, lockB) 39  t2.start() 40     print('嗯嗯,兩人不錯')
遞歸鎖

相關文章
相關標籤/搜索