python线程锁同步锁_Python 线程同步锁

1.多线程调用资源冲突

例子

1 #__author: Lobin

2 #__date: 2018/1/22

3 importthreading4 importtime5 num=100

6 defadd():7 globalnum8 #num-=1

9 temp=num10 #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 inthread_list:20 t.join()21

22 print('final num:',num)

解析:

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

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

例子

1 #__author: Lobin

2 #__date: 2018/1/22

3 importthreading4 importtime5 num=100

6 defadd():7 globalnum8 #num-=1

9 lock.acquire()10 temp=num11 #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 inthread_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 importthreading,time4

5 classmyThread(threading.Thread):6 defdoA(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 defdoB(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 defrun(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 inthreads:34 t.start()35 for t inthreads: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 importthreading,time4

5 classmyThread(threading.Thread):6 defdoA(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 defdoB(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 defrun(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 inthreads:35 t.start()36 for t inthreads: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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值