---恢复内容开始---
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 num11 12 13 def run2():14 print("grab the second part data")15 lock.acquire()16 global num217 num2 += 118 lock.release()19 return num220 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, 034 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 = 014 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 = 016 else:17 print('\033[42;1mgreen light \033[0m')18 19 time.sleep(1)20 count += 121 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 = 110 #for i in range(10):11 while True:12 q.put("骨头%s" %count) #%i)13 print("生产了骨头",count)14 count += 115 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()