Python 线程同步锁

1.多线程调用资源冲突

例子

 1 #__author: Lobin
 2 #__date:   2018/1/22
 3 import threading
 4 import time
 5 num=100
 6 def add():
 7     global num
 8     # num-=1
 9     temp=num
10     # print('ok')
11     time.sleep(0.0001)
12     num=temp-1
13 
14 thread_list=[]
15 for i in range(100):
16     t=threading.Thread(target=add)
17     t.start()
18     thread_list.append(t)
19 for t in thread_list:
20     t.join()
21 
22 print('final num:',num)

解析:

每次执行结果不同,由于time.sleep()使得CPU切换线程执行任务时,可能存在所取的变量的值被后一次调用覆盖的情况

 

2.同步锁将并行转为串行

例子

 1 #__author: Lobin
 2 #__date:   2018/1/22
 3 import threading
 4 import time
 5 num=100
 6 def add():
 7     global num
 8     # num-=1
 9     lock.acquire()
10     temp=num
11     # print('ok')
12     time.sleep(0.0001)
13     num=temp-1
14     lock.release()
15 
16 thread_list=[]
17 lock=threading.Lock()
18 for i in range(100):
19     t=threading.Thread(target=add)
20     t.start()
21     thread_list.append(t)
22 for t in thread_list:
23     t.join()
24 
25 print('final num:',num)

解析:

2.1 lock=threading.Lock()创建一个同步锁

2.2在所要转换的同步代码两端加上lock.acquire() 加锁,lock.release()解锁,在加锁后除非释放锁,其他线程不能访问这个代码

 

3.死锁

例子

 1 #__author: Lobin
 2 #__date:   2018/1/22
 3 import threading,time
 4 
 5 class myThread(threading.Thread):
 6     def doA(self):
 7         lockA.acquire()
 8         print(self.name,"gotlockA",time.ctime())
 9         time.sleep(3)
10         lockB.acquire()
11         print(self.name,"gotlockB",time.ctime())
12         lockB.release()
13         lockA.release()
14 
15     def doB(self):
16         lockB.acquire()
17         print(self.name,"gotlockB",time.ctime())
18         time.sleep(2)
19         lockA.acquire()
20         print(self.name,"gotlockA",time.ctime())
21         lockA.release()
22         lockB.release()
23     def run(self):
24         self.doA()
25         self.doB()
26 if __name__=="__main__":
27 
28     lockA=threading.Lock()
29     lockB=threading.Lock()
30     threads=[]
31     for i in range(5):
32         threads.append(myThread())
33     for t in threads:
34         t.start()
35     for t in threads:
36         t.join()#等待线程结束,后面再讲。

结果为:

1 #Thread-1 gotlockA Mon Jan 22 20:21:53 2018
2 #Thread-1 gotlockB Mon Jan 22 20:21:56 2018
3 #Thread-1 gotlockB Mon Jan 22 20:21:56 2018
4 #Thread-2 gotlockA Mon Jan 22 20:21:56 2018

解析:

当线程1执行完A函数时,锁A和锁B都处于释放状态,线程1执行B函数获得锁B,线程2进入A函数获得A锁,当各自执行到需要对方的锁时,进入死锁状态

 

4.解决方案:使用递归锁

为了支持在同一线程中多次请求同一资源,python提供了“可重入锁”:threading.RLock。

RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次acquire。

直到一个线程所有的acquire都被release,其他的线程才能获得资源。

例子:

 1 #__author: Lobin
 2 #__date:   2018/1/22
 3 import threading,time
 4 
 5 class myThread(threading.Thread):
 6     def doA(self):
 7         lock.acquire()
 8         print(self.name,"gotlockA",time.ctime())
 9         time.sleep(3)
10         lock.acquire()
11         print(self.name,"gotlockB",time.ctime())
12         lock.release()
13         lock.release()
14 
15     def doB(self):
16         lock.acquire()
17         print(self.name,"gotlockB",time.ctime())
18         time.sleep(2)
19         lock.acquire()
20         print(self.name,"gotlockA",time.ctime())
21         lock.release()
22         lock.release()
23     def run(self):
24         self.doA()
25         self.doB()
26 if __name__=="__main__":
27 
28     # lockA=threading.Lock()
29     # lockB=threading.Lock()
30     lock=threading.RLock()
31     threads=[]
32     for i in range(5):
33         threads.append(myThread())
34     for t in threads:
35         t.start()
36     for t in threads:
37         t.join()#等待线程结束

结果:

 1 #Thread-1 gotlockA Mon Jan 22 20:27:44 2018
 2 #Thread-1 gotlockB Mon Jan 22 20:27:47 2018
 3 #Thread-1 gotlockB Mon Jan 22 20:27:47 2018
 4 #Thread-1 gotlockA Mon Jan 22 20:27:49 2018
 5 #Thread-3 gotlockA Mon Jan 22 20:27:49 2018
 6 #Thread-3 gotlockB Mon Jan 22 20:27:52 2018
 7 #Thread-3 gotlockB Mon Jan 22 20:27:52 2018
 8 #Thread-3 gotlockA Mon Jan 22 20:27:54 2018
 9 #Thread-5 gotlockA Mon Jan 22 20:27:54 2018
10 #Thread-5 gotlockB Mon Jan 22 20:27:57 2018
11 #Thread-5 gotlockB Mon Jan 22 20:27:57 2018
12 #Thread-5 gotlockA Mon Jan 22 20:27:59 2018
13 #Thread-4 gotlockA Mon Jan 22 20:27:59 2018
14 #Thread-4 gotlockB Mon Jan 22 20:28:02 2018
15 #Thread-4 gotlockB Mon Jan 22 20:28:02 2018
16 #Thread-4 gotlockA Mon Jan 22 20:28:04 2018
17 #Thread-2 gotlockA Mon Jan 22 20:28:04 2018
18 #Thread-2 gotlockB Mon Jan 22 20:28:07 2018
19 #Thread-2 gotlockB Mon Jan 22 20:28:07 2018
20 #Thread-2 gotlockA Mon Jan 22 20:28:09 2018

posted on 2018-01-22 21:24  可爱的春哥  阅读(150)  评论(0)    收藏  举报

导航