递归锁
一把大锁在加一把小锁。
import threading import 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.Lock() 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)
过程分享:
1、启动10个线程,每个线程都执行run3。
2、run3中先加了一个锁,然后执行run1。
3、run1中也加了一个锁,计算完成后解锁返回数据。执行run2。
4、run2中同样加了一个锁,计算完成后解锁打印run1,run2返回值。
5、最后打印num1、num2。
需要注意的是在执行过程中是有两把锁的,一个run3,一个run1或者run2。
运行结果:
11 11 11 11 11 11 11 11 # 程序进入死循环
死循环的原因是解锁的时候 钥匙拿错了导致进程退不出来,解决死锁就是要使用递归锁。
threading.Lock() 改为 threading.RLock()
import threading import 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(1): t = threading.Thread(target=run3) t.start() while threading.active_count() != 1: print(threading.active_count()) else: print('----all threads done---') print(num, num2)
运行结果
grab the first part data --------between run1 and run2----- grab the second part data 1 1 ----all threads done--- 1 1
实现原理:
解锁的时候找对应的钥匙。
信号量
互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。简单的说就是互斥锁同一时间只能要一个线程修改数据,信号量同一时间可以让多个线程修改数据。信号量可以挂多吧锁。
import threading,time def run(n): semaphore.acquire() time.sleep(1) print("run the thread: %s " %n) semaphore.release() if __name__ == '__main__': num= 0 semaphore = threading.BoundedSemaphore(5) #最多允许5个线程同时运行 for i in range(20): t = threading.Thread(target=run,args=(i,)) t.start() while threading.active_count() != 1: pass #print threading.active_count() else: print('----all threads done---') print(num)
每一个进程结束了就重新添加一个新的进去。