python的多线程+GIL全局解释器锁+其他LOCK
---恢复内容开始---
python的多线程实际上只有一个线程。
为了让各个线程能够平均利用CPU时间,python会计算当前已执行的微代码数量,达到一定阈值后就强制释放GIL。而这时也会触发一次操作系统的线程调度(当然是否真正进行上下文切换由操作系统自主决定)。
GIL全局解释器锁: 保证同一时间只有一个线程得到数据并且只有一个线程执行,但是cpu调度时间到了以后,第一个线程无论是否完成均程等待状态(若未执行完毕,数据放入寄存器中)下一线程得到的依旧是原始的公共数据。
用户级lock:保证同一时间只有一个线程在修改数据。(可以避免几个线程同时对公共原始数据进行修改,提高线程效率)
为公共数据Lock:一个线程修改后,释放,下一进程才可再次进行修改。
RLock(递归锁):在一个大锁中还要再包含子锁
1 import threading, time 2 3 4 def run1(): 5 print("grab the first part data") 6 lock.acquire() 7 global num 8 num += 1 9 lock.release() 10 return num 11 12 13 def run2(): 14 print("grab the second part data") 15 lock.acquire() 16 global num2 17 num2 += 1 18 lock.release() 19 return num2 20 21 22 def run3(): 23 lock.acquire() 24 res = run1() 25 print('--------between run1 and run2-----') 26 res2 = run2() 27 lock.release() 28 print(res, res2) 29 30 31 # if __name__ == '__main__': 32 33 num, num2 = 0, 0 34 lock = threading.RLock() 35 for i in range(10): 36 t = threading.Thread(target=run3) 37 t.start() 38 39 while threading.active_count() != 1: 40 print(threading.active_count()) 41 else: 42 print('----all threads done---') 43 print(num, num2)
线程锁(互斥锁Mutex)
信号量:和单个锁的区别是信号量有多个锁
1 import threading, time 2 3 # 信号量就是多个锁 4 def run(n): 5 semaphore.acquire()#信号量获取 6 time.sleep(1) 7 print("run the thread: %s\n" % n) 8 semaphore.release() # 信号量释放 9 10 11 if __name__ == '__main__': 12 13 num = 0 14 semaphore = threading.BoundedSemaphore(5) # 最多允许5个线程同时运行 15 for i in range(20): 16 t = threading.Thread(target=run, args=(i,)) 17 t.start() 18 19 while threading.active_count() != 1: 20 pass # print threading.active_count() 21 else: 22 print('----all threads done---') 23 print(num)
事件Event:实现红绿灯
概念&涉及知识点:
事件是一个简单的同步对象;代表一个内部标志,线程可以等待设置标志,或者自己设置或清除标志。
#客户端线程可以等待设置标志 event.wait()
#a服务器线程可以设置或重置它 event.set() event.clear()
如果设置了标志,则wait方法不会执行任何操作。
如果该标志被清除,则等待将被阻塞,直到它再次被设置为止。
任意数量的线程都可以等待同一事件。
1 import time 2 import threading 3 4 event = threading.Event() 5 def Lighter(): 6 count = 0 7 event.set() 8 while True: 9 if count >5 and count <10: # 改成红灯 10 #无标志位会显示等待,有标志位是通行。 wait是通行 11 event.clear() #清空标志位 12 print('\033[41;1mred light \033[0m') 13 elif count >10: 14 event.set() # 设置标志位,变绿灯 15 count = 0 16 else: 17 print('\033[42;1mgreen light \033[0m') 18 19 time.sleep(1) 20 count += 1 21 22 def car(name): 23 while True: 24 if event.is_set(): #代表绿灯 25 time.sleep(1) 26 print('[%s] running '%name) 27 else: 28 print('[%s] sees red light ,waiting '%name) 29 event.wait() 30 print('\033[34;1m[%s] green light is on ,start going \033[0m'%name) 31 32 light = threading.Thread(target=Lighter,) 33 light.start() 34 35 car1 = threading.Thread(target=car,args=('Car1',)) 36 car1.start()
队列:使程序之间实现松耦合,提高处理效率。
两种模式:
FIFO = first in first out
LIFO = last in first out
队列和列表的区别:
队列:数据取出后,队列中就没有此数据了。
列表;数据取出进行操作,但是列表中仍旧有原数据。
生产者与消费者模式(做解耦):
1 import threading,time 2 3 import queue 4 5 q = queue.Queue() 6 q.maxsize = 10 7 8 def Producer(name): 9 count = 1 10 #for i in range(10): 11 while True: 12 q.put("骨头%s" %count) #%i) 13 print("生产了骨头",count) 14 count += 1 15 time.sleep(2) 16 17 18 def Consumer(name): 19 while True: 20 print("[%s]取到[%s]并且吃了它" %(name, q.get())) 21 time.sleep(1) 22 23 p = threading.Thread(target=Producer, args=("lex",)) 24 c1 = threading.Thread(target=Consumer, args=("chen",)) 25 c2 = threading.Thread(target=Consumer, args=("wang",)) 26 27 p.start() 28 c1.start() 29 c2.start()
浙公网安备 33010602011771号