并发&并行 同步&异步 GIL 任务 同步锁 死锁 递归锁
# 并发&并行 同步&异步 GIL 任务 同步锁 死锁 递归锁 # 并发:是指系统具有处理多个任务(动作)的能力 # 并行:是指系统具有 同时 处理多个任务(动作)的能力 # 同步:当进程执行到一个IO(等待外部数据)的时候,需要等待外部数据接收完 # 异步:当进程执行到一个IO(等待外部数据)的时候,不需要等待外部数据接收完,还可以做其它的处理 # GIL: 全局解释器锁 在python中,无论你启多少个线程,你有多少个cpu,python在执行的时候在同一时刻只请允许一个线程运行 # 任务:IO密集型(python的多线程是有意义的,或使用多进程+协程) 计算密集型(python的多线程就不推荐,python就不适用了) # 同步锁 import threading, time num = 100 def sub(): global num temp = num time.sleep(0.00001) num = temp - 1 l = [] # 定义一个空列表 for i in range(100): # 循环100次 t = threading.Thread(target=sub) # 通过循环创建100个线程t对象并放入列表中 t.start() l.append(t) for t in l: # 循环列表,让每一个线程对象t执行join() t.join() print(num) # 99 居然不是0,问题在哪里? # 因为此时是IO操作,当第一个线程取到100后要睡1秒,这时还没有减1,这时第二个线程又来取值,值还是100,只要cpu执行速度越快,所有的线程来取值时都是100,意味着100个线程都拿到num为100 # 如果sleep(0.00001),这时最终值又会变为92。这里的值与cpu调度的各线程IO操作的时间有关,sleep时间越短,各个线程拿到num为100时的情况就越少 # 解决方法,加上同步锁,在同一时间只允许一个线程对num操作 import threading, time num = 100 def sub(): global num lock.acquire() # 加锁 temp = num time.sleep(0.00001) num = temp - 1 lock.release() # 解锁 l = [] # 定义一个空列表 lock = threading.Lock() # 创建同步锁 for i in range(100): # 循环100次 t = threading.Thread(target=sub) # 通过循环创建100个线程t对象并放入列表中 t.start() l.append(t) for t in l: # 循环列表,让每一个线程对象t执行join() t.join() print(num) # 0 # 一个死锁的例子 第一个线程需要A锁(A锁已被第二个线程占用),第二个线程需要B锁(B锁已被第一个线程占用)。结果谁也不让造成死锁 import threading, time class MyThread(threading.Thread): def actionA(self): A.acquire() print(self.name, 'gotA', time.ctime()) time.sleep(2) B.acquire() print(self.name, 'gotB', time.ctime()) time.sleep(2) B.release() A.release() def actionB(self): B.acquire() print(self.name, 'gotB', time.ctime()) time.sleep(2) A.acquire() print(self.name, 'gotA', time.ctime()) time.sleep(2) A.release() B.release() def run(self): self.actionA() self.actionB() if __name__ == '__main__': A = threading.Lock() B = threading.Lock() l = [] for i in range(5): t = MyThread() t.start() l.append(t) for i in l: t.join() print('end...') # 解决死锁的方案,使用递归锁 import threading, time class MyThread(threading.Thread): def actionA(self): r_lock.acquire() print(self.name, 'gotA', time.ctime()) time.sleep(2) r_lock.acquire() print(self.name, 'gotB', time.ctime()) time.sleep(2) r_lock.release() r_lock.release() def actionB(self): r_lock.acquire() print(self.name, 'gotB', time.ctime()) time.sleep(2) r_lock.acquire() print(self.name, 'gotA', time.ctime()) time.sleep(2) r_lock.release() r_lock.release() def run(self): self.actionA() self.actionB() if __name__ == '__main__': r_lock = threading.RLock() # 这里创建的是递归锁,将原来的两把锁AB换成一把锁 # 哪个线程拿到r_lock锁,只有等它完全释放后,其它的线程才能再拿这个锁 l = [] for i in range(5): t = MyThread() t.start() l.append(t) for i in l: t.join() print('end...')