互斥锁,递归锁,信号量
互斥锁,递归锁,信号量
以上都是进程(线程)锁,下面我就一一解释一下
最普通互斥锁
from threading import Thread,Lock import time def work(): l.acquire() time.sleep(1) print('ok') l.release() if __name__ == '__main__': l = Lock() t_l = [] start = time.time() for i in range(10): t = Thread(target=work) t_l.append(t) t.start() for t in t_l: t.join() print(time.time()-start)
看一下最后执行时间,如果没有互斥锁,线程是并行执行,时间在1s多点,而有互斥锁后,线程变成串行执行,时间是10s多点,
它有什么作用:保证同一时间只有一个进程(线程在修改数据,从而使修改的共享数据安全),也是为什么Cpython解释器不能在同一进程内真正意义上并发线程(GIL锁)
递归锁
作用:拥有多重引用机制,简单来说,这个锁功能和互斥锁功能一样,但多了个计数功能,一个锁可以引用多次,引用几次要释放几次,如果引用次数不清空,下一个进程(线程)不能进行锁的引用
from threading import Thread,RLock import time mutex = RLock() class My_thread(Thread): def __init__(self): super().__init__() self.count = 0 def run(self): self.f1() self.f2() def f1(self): mutex.acquire() self.count += 1 time.sleep(0.5) print('%s is use lock %s'%(self.getName(),self.count)) mutex.acquire() self.count += 1 time.sleep(0.5) print('%s is use lock %s' % (self.getName(), self.count)) mutex.release() self.count -= 1 print('%s is use lock %s' % (self.getName(), self.count)) mutex.release() self.count -= 1 print('%s is use lock %s' % (self.getName(), self.count)) def f2(self): mutex.acquire() time.sleep(0.5) self.count += 1 print('%s is use lock %s' % (self.getName(), self.count)) mutex.acquire() self.count += 1 time.sleep(0.5) print('%s is use lock %s' % (self.getName(), self.count)) mutex.release() self.count -= 1 print('%s is use lock %s' % (self.getName(), self.count)) mutex.release() self.count -= 1 print('%s is use lock %s' % (self.getName(), self.count)) if __name__ == '__main__': for i in range(10): t = My_thread() t.start()
以上代码的效果是线程全部串行执行(哪个线程抢到锁哪个执行,不一定线程会按顺序执行)
信号量
作用:同时生成多把锁,有几把锁就能同时运行几个进程(线程),有点类似进程池,不同电视,进程池会一直运行到没有任务了,开的进程才会死,就是说不管你运行多少任务,给你执行的进程就是原来执行完任务的进程,人家等着你给下一个任务呢,他还是他一直存活;信号量是有几个(进程)线程得到锁后开始执行,执行完就死了,下一个拿锁的就执行,但下一个进程(线程)已经不是原来的进程(线程)了,他是新的,原来的已经死了
from threading import Thread,Semaphore,currentThread import time,random se = Semaphore(5) def work(): se.acquire() print('%s is running'%currentThread().getName()) time.sleep(random.randint(1,4)) print('%s is done' % currentThread().getName()) se.release() if __name__ == '__main__': t_l = [] for i in range(30): t = Thread(target=work) t_l.append(t) t.start() for t in t_l: t.join()