锁,Event,semaphore
GIL:全局解释锁:无论开启多少个线程,同一时刻只允许执行一个线程运行(解释器级别,保护数据)
锁:两种状态,锁定和未锁定,仅支持两个函数,获得锁和释放锁
多线程抢夺锁时,当某个线程获得锁了,其他的锁都会被阻塞,直到这个线程释放锁后,其他线程才可以再抢夺锁,注意线程抢夺锁是没有顺序的
同步锁:Lock,与GIL不同,它是用户层面上的,由用户自定义
import threading import time def sub(): global num # 加上一个锁,使得本来并发的变成串行,用来保护自己的数据不被其他的线程拿到 lock.acquire() #获得锁 temp = num time.sleep(0.01) #当阻碍时间较长时,其他的线程可能也会拿到这个数据 num = temp - 1 lock.release() #释放锁 num = 100 l = [] lock = threading.Lock() #声明一个锁 for i in range(100): t = threading.Thread(target=sub) t.start() l.append(t) for t in l: t.join() print(num)
死锁:当存在多线程时,双方都在等对方释放锁,产生死锁,当无外力作用时,程序将无法推进下去
递归锁:RLock内部维护着一个counter,每次acquire都会使得counter + 1 ,每release一次counter - 1,
当counter大于0时,只能有一个线程可以获得这个锁,只有等于0时,其他线程才能获得这个锁
import threading import time class MyThread(threading.Thread): def action1(self): t1.acquire() print(self.name,"got t1",time.ctime) time.sleep(2) t2.acquire() print(self.name,"got t2",time.ctime) time.sleep(2) t2.release() t1.release() def action2(self): t2.acquire() print(self.name, "got t2", time.ctime) time.sleep(2) t1.acquire() print(self.name, "got t1", time.ctime) time.sleep(2) t1.release() t2.release() def run(self): self.action1() self.action2() if __name__ == '__main__': t1 = threading.Lock() t2 = threading.Lock() L = [] for i in range(5): t = MyThread() t.start() L.append(t) for t in L: t.join() print("end...")
解决产生死锁:使用递归锁,t1,t2的锁声明改为 threading.RLock()
同步条件:Event
#创建Event对象
event = threading.Event
3个方法
#a client thread wait for the flag to be set
event.wait()
#a server thread can set or reset it
event.set()
event.clear()
使用规则
if the flag is set , the wait method doesn't do anything
if the flag is cleared ,the wait block until it becomes set again
any number of threads may wait for the same event
import threading,time class Boss(threading.Thread): def run(self): print("BOSS:everybody works overtime tonight。") print(event.isSet()) event.set() time.sleep(5) print("BOSS:can leave work。") print(event.isSet()) event.set() class Worker(threading.Thread): def run(self): event.wait() #当Event没有set时,wait方法被调用,阻塞,当Event被set后,这个wait方法就相当于pass print("Worker:ah……life is bitter!") time.sleep(1) event.clear() event.wait() print("Worker:OhYeah!") if __name__=="__main__": event=threading.Event() threads=[] for i in range(5): threads.append(Worker()) threads.append(Boss()) for t in threads: t.start() for t in threads: t.join()
信号量:Semaphore
用来控制线程并发数,当同时并发的线程达到指定的最大数时,其他线程将会被阻塞
BoundedSemaphore或Semaphore内置一个计数器,当acquire()时 -1,当release()时 +1,
计数器不能小于0,当计数器等于0时,acquire()将线程阻塞同步至锁定状态,直到有线程release()释放
BoundedSemaphore和Semaphore的区别:BoundedSemaphore在调用release()检测计数器是否超过设定值,达到抛出一个异常
import threading,time class myThread(threading.Thread): def run(self): if semaphore.acquire(): print(self.name) time.sleep(5) semaphore.release() if __name__=="__main__": semaphore=threading.Semaphore(5) #设置可以同时有几个线程并发 thrs=[] for i in range(100): thrs.append(myThread()) for t in thrs: t.start()