Python3 并发编程3,, 目录
Python3 并发编程3,, 目录
目录
GIL全局解释器锁 基本概念 多线程的作用 死锁现象 递归锁 信号量 线程队列GIL全局解释器锁
基本概念
global interpreter lock 全局解释器锁GIL不是Python的特性, 是Cpython解释器的特性GIL本质是一个互斥锁原因: Cpython解释器的内存管理不是线程安全的作用: 保证同一时间一个线程内只有一个线程在执行多线程的作用
计算密集型---多进程, GIL原因, 一个进程内的线程只能并发, 不能并行I/O密集型---多线程, 开启线程与切换线程的速度要快于进程# 计算密集型import timeimport osfrom multiprocessing import Processfrom threading import Thread# 计算密集型def task1(): number = 0 for i in range(100000000): number += 1 print('done!')if __name__ == '__main__': start_time = time.time() lis = [] for i in range(4): # p = Process(target=task1) # 程序执行时间为16.711955785751343 t = Thread(target=task1) # 程序执行时间为26.467514038085938 lis.append(t) t.start() for t in lis: t.join() end_time = time.time() print(f'程序执行时间为{end_time - start_time}')
# I/O密集型import timeimport osfrom multiprocessing import Processfrom threading import Thread# I/O密集型def task2(): time.sleep(1)if __name__ == '__main__': start_time = time.time() lis = [] for i in range(20): # p = Process(target=task2) # 程序执行时间为5.277301788330078 t = Thread(target=task2) # 程序执行时间为1.0040574073791504 lis.append(t) t.start() for t in lis: t.join() end_time = time.time() print(f'程序执行时间为{end_time - start_time}')
死锁现象
两个或者两个以上的线程在执行过程中, 因为争夺资源而产生的相互等待的状况from threading import Thread, Lockimport timemutex_a = Lock()mutex_b = Lock()class MyThread(Thread): def run(self): self.func1() self.func2() def func1(self): mutex_a.acquire() print(f'{self.name}拿到了锁a') mutex_b.acquire() print(f'{self.name}拿到了锁b') mutex_b.release() print(f'{self.name}释放了锁b') mutex_a.release() print(f'{self.name}释放了锁a') def func2(self): mutex_b.acquire() print(f'{self.name}拿到了锁b') # I/O操作 time.sleep(1) mutex_a.acquire() print(f'{self.name}拿到了锁a') mutex_a.release() print(f'{self.name}释放了锁a') mutex_b.release() print(f'{self.name}释放了锁b')if __name__ == '__main__': for i in range(4): t = MyThread() t.start() '''Thread-1拿到了锁aThread-1拿到了锁bThread-1释放了锁bThread-1释放了锁aThread-1拿到了锁bThread-2拿到了锁a'''
递归锁
RLock 内部维护一个Lock和一个计数的counter, counter记录了acquire次数, 使得资源可以被多次请求直到一个线程所有的acquire都被release, 其他线程才能获取资源from threading import Thread, RLockimport timemutex_a = mutex_b = RLock()class MyThread(Thread): def run(self): self.func1() self.func2() def func1(self): mutex_a.acquire() print(f'{self.name}拿到了锁a') mutex_b.acquire() print(f'{self.name}拿到了锁b') mutex_b.release() print(f'{self.name}释放了锁b') mutex_a.release() print(f'{self.name}释放了锁a') def func2(self): mutex_b.acquire() print(f'{self.name}拿到了锁b') # I/O操作 time.sleep(3) mutex_a.acquire() print(f'{self.name}拿到了锁a') mutex_a.release() print(f'{self.name}释放了锁a') mutex_b.release() print(f'{self.name}释放了锁b')if __name__ == '__main__': for i in range(4): t = MyThread() t.start()'''Thread-1拿到了锁aThread-1拿到了锁bThread-1释放了锁bThread-1释放了锁aThread-1拿到了锁b---间隔了3秒---Thread-1拿到了锁aThread-1释放了锁aThread-1释放了锁bThread-2拿到了锁aThread-2拿到了锁bThread-2释放了锁bThread-2释放了锁aThread-2拿到了锁b---间隔了3秒---Thread-2拿到了锁aThread-2释放了锁aThread-2释放了锁bThread-4拿到了锁aThread-4拿到了锁bThread-4释放了锁bThread-4释放了锁aThread-4拿到了锁b---间隔了3秒---Thread-4拿到了锁aThread-4释放了锁aThread-4释放了锁bThread-3拿到了锁aThread-3拿到了锁bThread-3释放了锁bThread-3释放了锁aThread-3拿到了锁bThread-3拿到了锁aThread-3释放了锁aThread-3释放了锁b'''
信号量
from threading import Semaphore相当于多个互斥锁, 可以控制多个线程来访问数据 (可以控制访问资源的线程数量)sm = Semaphore(5) 表示一次允许5个线程访问数据acquire 一次, 括号内数字减一, release一次加一, 为0时限制其他线程访问from threading import Thread, Semaphore, current_threadimport time# 一次允许5个线程访问数据sm = Semaphore(5)def task(): sm.acquire() print(f'{current_thread().name}已运行...') time.sleep(3) sm.release()if __name__ == '__main__': for i in range(20): t = Thread(target=task) t.start() '''Thread-1已运行...Thread-2已运行...Thread-3已运行...Thread-4已运行...Thread-5已运行...---间隔了3秒---Thread-6已运行...Thread-7已运行...Thread-8已运行...Thread-9已运行...Thread-10已运行...--间隔了3秒---Thread-11已运行...Thread-12已运行...Thread-13已运行...Thread-14已运行...Thread-15已运行...---间隔3秒---Thread-17已运行...Thread-16已运行...Thread-18已运行...Thread-19已运行...Thread-20已运行...'''
线程队列
queue.Queue()FIFO 先进先出queque.LifoQueue() LIFO 后进先出queque.PriorityQueue() 优先级, 根据元祖内的数据排序import queue# 先进先出 FIFOq1 = queue.Queue()q1.put(1)q1.put(2)q1.put(3)print(q1.get()) # 1# 后进先出 LILOq2 = queue.LifoQueue()q2.put(1)q2.put(2)q2.put(3)print(q2.get()) # 3# 优先级 按元祖内的数据排序q3 = queue.PriorityQueue()q3.put(('a',))q3.put(('b',))q3.put(('c',))print(q3.get()) # ('a',)
Python3 并发编程3
评论关闭