在这里不详细多说,关于GIL全局性解释器锁的详细信息,有兴趣可以参考:https://www.cnblogs.com/cjaaron/p/9166538.html
我们最重要的是需要理解,Python多线程适合IO密集型操作,但在计算密集型操作中,多线程甚至没有单线程快。
再来讲互斥锁(也就是线程锁)
当多个线程同时修改一个数据的时候,可能会发生无法预估的错误,所以这时候要上锁。在这里叫做互斥锁。
def run():
lock.acquire() # 获取锁
global num
num += 1
lock.release() # 释放锁
time.sleep(1)
if __name__ == "__main__":
lock = threading.Lock() # 生成锁的实例
num = 0
obj = []
start = time.time()
for i in range(1000):
t= threading.Thread(target=run)
t.start()
obj.append(t)
for j in obj:
j.join()
end = time.time()
cost = end - start
print("cost time:",cost)
print("num:",num)
递归锁
互斥锁之间可以嵌套,但是没有理清逻辑容易造成死锁,无法解开。这里使用递归锁,实现多层上锁和多层解锁
def run1():
print("grab the first part data")
lock.acquire()
global num
num += 1
lock.release()
return num
def run2():
print("grab the second part data")
lock.acquire()
global num2
num2 += 1
lock.release()
return num2
def run3():
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res, res2)
if __name__ == '__main__':
num, num2 = 0, 0
lock = threading.RLock() # 递归锁,设锁和解锁必须是成对的
for i in range(10):
t = threading.Thread(target=run3)
t.start()
while threading.active_count() != 1:
print(threading.active_count())
else:
print('----all threads done---')
print(num, num2)
需要注意的是:上锁和解锁必须是成对的。
信号量
信号量其实也是一种锁,用于限制线程的并发量,即同一时间只允许几个线程运行。
def run(n):
semaphore.acquire()
time.sleep(1)
print("run the thread: {0}\n".format(n))
semaphore.release()
if __name__ == '__main__':
semaphore = threading.BoundedSemaphore(5) # 最多允许5个线程同时运行
for i in range(20):
t = threading.Thread(target=run, args=(i+1,))
t.start()
while threading.active_count() != 1:
pass # print threading.active_count()
else:
print('----all threads done---')
Timer
创建一个有延迟的线程。
def hello():
print("hello, world")
t = Timer(30.0, hello)
t.start() # 30秒后执行此线程
Event
threading.Event()用来实现两个或多个线程之间的交互
有四个方法:
set() 设置标志位
clear()清空标志位
wait()如果已经设置标志位不会阻塞,如果没有设置标志位则产生阻塞
isSet() 判定是否设置了标志位。
接下来是一个车等红绿灯的例子,车是停还是行需要根据红绿灯来判定。将实例化若干个车(线程)和一个红绿灯(线程),来实现线程间交互
import threading
import time
import random
def light():
"红绿灯"
while True:
count = 1
event.set() # 标志位设定了,wait就不阻塞 #绿灯状态
while True:
if count == 1:
print('\033[42;1m--green light on---\033[0m')
time.sleep(10)
count = 2
elif count == 2:
print('\033[43;1m--yellow light on---\033[0m')
time.sleep(2)
count = 3
elif count == 3:
event.clear() # 标志位被清空,wait()阻塞
print('\033[41;1m--red light on---\033[0m')
time.sleep(10)
break