目录
? 1、GIL本质是一个互斥锁
? 2、GIL是为了阻止同一个进程内的多个线程同时执行(并行)
? 单个进程下的多个线程无法实现并行,但能实现并发
? 3、这把锁主要是因为CPython的内存管理不是“线程安全的”
? 垃圾回收机制
? 多个线程过来执行,一旦遇到IO操作,就会立马释放GIL解释器锁,交给下一个先进来的线程.
import time
from threading import Thread, current_thread
number = 10
def task():
global number
number2 = number
# time.sleep(1) # 加延迟和不加延迟的结果不同,
number =number2 - 1
print(number, current_thread().name)
for line in range(10):
t = Thread(target=task) 实现
t.start()
? 站在任务角度去看问题: 任务偏向于 IO密集型 还是 计算密集型
假设有四个任务, 每个任务需要10s,对比如下:
计算密集型:单核:用多进程:资源消耗过大, 4个进程40s
用多线程:资源消耗小, 4个线程40s
多核:用多进程:并行执行,效率较高, 4个进程10s
用多线程:并发执行,效率低, 4个线程40s
IO密集型:单核:用多进程:资源消耗过大, 4个进程40s
用多线程:资源消耗小, 4个线程40s
多核:用多进程:并行执行,效率小于多线程,因为遇到IO会切换CPU的执行权限,10s+切换
用多线程:并发执行,效率低,4个线程40s
import time
from multiprocessing import Process
from threading import Thread
def work1(): # 计算密集型任务
number = 0
for line in range(100000000):
number += 1
def work2(): # IO密集型任务
time.sleep(1)
# 验证计算密集型:
if __name__ == '__main__':
start_time = time.time()
list1 = []
for line in range(6):
# p = Process(target=work1) # 程序执行时间是: -8.197991132736206
p = Thread(target=work1) # 程序执行时间是-44.56647181510925
list1.append(p)
p.start()
for p in list1:
p.join()
end_time = time.time()
print(list1)
print(f'程序执行时间是{start_time - end_time}')
# 验证IO密集型
if __name__ == '__main__':
start_time = time.time()
lis = []
for i in range(50):
p = Process(target=work2) # 程序执行时间是:7.335782766342163
# p = Thread(target=work2) # 程序执行时间是:1.0078797340393066
lis.append(p)
p.start()
for p in lis:
p.join()
end_time = time.time()
print(f'程序执行时间是:{end_time - start_time}')
在计算密集型的情况下: 使用多进程
在IO密集型的情况下: 使用多线程
高效执行多个进程,内多个IO密集型的程序: 使用 多进程 + 多线程
from threading import Lock, Thread, current_thread
import time
mutex_a = Lock() # 得到锁a
mutex_b = Lock() # 得到锁b
#
# print(id(mutex_a))
# print(id(mutex_b))
class MyThread(Thread): # 定义线程类
# 线程执行任务
def run(self):
self.func1()
self.func2()
def func1(self): # 任务一
mutex_a.acquire()
# print(f'用户{current_thread().name}抢到锁a')
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')
time.sleep(1) # IO操作
mutex_a.acquire()
print(f'用户{self.name}抢到锁a')
mutex_a.release()
print(f'用户{self.name}释放锁a')
mutex_b.release()
print(f'用户{self.name}释放锁b')
for line in range(10): # 循环开启10个线程
t = MyThread()
t.start()
运行结果:
用户Thread-1抢到锁a
用户Thread-1抢到锁b
用户Thread-1释放锁b
用户Thread-1释放锁a
用户Thread-1抢到锁b
用户Thread-2抢到锁a # 线程2 拿不到锁b,卡死
用于解决死锁问题.
RLock: 比喻成万能锁,可以提供给多个人去使用.但是第一个使用的时候,会对该锁做一个引用计数.
只有引用计数为0, 才能真正释放让另一个人去使用
from threading import RLock, Thread, Lock
import time
mutex_a = mutex_b = RLock() # 注意:此处是RLock
class MyThread(Thread):
# 线程执行任务
def run(self):
self.func1()
self.func2()
def func1(self):
mutex_a.acquire()
# print(f'用户{current_thread().name}抢到锁a')
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')
# IO操作
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')
for line in range(10):
t = MyThread()
t.start()
互斥锁: 同一时间只能让一个线程或进程使用
信号量: 同一时间只能让指定个线程或进程使用, 可以理解为限流
from threading import Semaphore, Lock
from threading import current_thread
from threading import Thread
import time
sm = Semaphore(5) # 指定5个,意思是允许5个线程同一时间并发,相当于一个流量阀
mutex = Lock()
def task():
# mutex.acquir
sm.acquire() # 加流量阀
print(f'{current_thread().name}执行任务')
time.sleep(2)
sm.release() # 解流量阀
# mutex.release()
for line in range(20):
t = Thread(target=task)
t.start()
按数据的存取方式分,今天了解以下三种队列:
import queue
q = queue.Queue()
q.put(1)
q.put(2)
q.put(3)
print(q.get()) # 1
import queue
q = queue.LifoQueue()
q.put(1)
q.put(2)
q.put(3)
print(q.get()) # 3
队列元素一般以元组的形式存在。
根据各元素的字符顺序依次比较各字符对应的编码,编码数值小的优先
import queue
q = queue.PriorityQueue()
q.put(('a优', '先', '娃娃头', 4))
q.put(('a先', '优', '娃娃头', 3))
q.put(('a级', '级', '娃娃头', 2))
原文:https://www.cnblogs.com/allenchen168/p/11729475.html