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

评论关闭