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('嗯嗯,两人不错')
递归锁

相关文章
相关标签/搜索