博客整理day30
GIL全局解释器锁
对python虚拟机的访问是由全局解释器锁(GIL)来控制,有了这个全局解释器锁可以保证同一时刻只有一个线程在运行
-
GIL本质上是一个互斥锁
-
GIL的目的是为了阻止同一个进程内多个线程同时执行(并发)
单个进程下的多个线程无法实现并行,但能实现并发
-
这把锁主要是因为Cpython的内存管理不是'线程安全'的
内存管理
垃圾回收机制
GIL的存在就是为了保证线程安全
attention : 多个线程一同来执行,一旦遇到IO操作,就会立马释放GIL解释器锁,交给下一个先进来的线程
import time
from threading import Thread,current_thread
number = 100
def task():
global number
time.sleep(1)
number -= 1
print(number,current_thread().name)
for line in range(100):
t = Thread(target= task)
t.start()
多线程和多进程
在计算密集型的情况下:
使用多进程
在IO密集型的情况下:
使用多线程
高效执行多个进程,内多个IO密集型的程序:
使用 多进程 + 多线程
计算密集型
from threading import Thread
from multiprocessing import Process
import time
#计算密集型
def work1():
number = 0
for line in range(1000000):
number += 1
if __name__ == '__main__':
# #计算密集型测试
# start_time = time.time()
# list1 = []
# for line in range(6):
# # p = Process(target = work1)
# p = Thread(target = work1)
# list1.append(p)
# p.start()
for p in list1:
p.join()
end_time = time.time()
print(f'程序执行时间{end_time-start_time}')
IO密集型
#IO密集型
def work2():
time.sleep(1)
if __name__ == '__main__':
#IO密集型
start_time = time.time()
list1 = []
for line in range(40):
# p = Process(target=work2)
p = Thread(target=work2)
list1.append(p)
p.start()
for p in list1:
p.join()
end_time = time.time()
print(f'程序执行时间{end_time-start_time}')
死锁现象和递归锁
死锁
死锁指的是两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,他们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程成为死锁进程
from threading import Lock as Lock
import time
mutexA=Lock()
mutexB=Lock()
mutexA.acquire()
mutexA.acquire()
print(123)
mutexA.release()
mutexA.release()
递归锁RLock
在RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require,知道一个县城所有的acquire都被release,其他的线程才能获得资源
from threading import RLock, Thread
import time
mutex_a = mutex_b = 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个马桶
mutex = Lock() # 5个马桶
def task():
# mutex.acquire()
sm.acquire()
print(f'{current_thread().name}执行任务')
time.sleep(1)
sm.release()
# mutex.release()
for line in range(20):
t = Thread(target=task)
t.start()
线程队列
先进先出
import queue
q=queue.Queue()
q.put('first')
q.put('second')
q.put('third')
print(q.get())
print(q.get())
print(q.get())
'''
结果(先进先出):
first
second
third
'''
后进先出
import queue
q=queue.LifoQueue()
q.put('first')
q.put('second')
q.put('third')
print(q.get())
print(q.get())
print(q.get())
'''
结果(后进先出):
third
second
first
'''
优先级队列
1.首先根据第一个参数判断ascii表的数值大小
2.判断第个参数中的汉字顺序.
3.再判断第二参数中数字--> 字符串数字 ---> 中文
4.以此类推
import queue
q=queue.PriorityQueue()
#put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
q.put((20,'a'))
q.put((10,'b'))
q.put((30,'c'))
print(q.get())
print(q.get())
print(q.get())
'''
结果(数字越小优先级越高,优先级高的优先出队):
(10, 'b')
(20, 'a')
(30, 'c')
'''