---恢复内容开始---
python的多线程实际上只有一个线程。
为了让各个线程能够平均利用CPU时间,python会计算当前已执行的微代码数量,达到一定阈值后就强制释放GIL。而这时也会触发一次操作系统的线程调度(当然是否真正进行上下文切换由操作系统自主决定)。
GIL全局解释器锁: 保证同一时间只有一个线程得到数据并且只有一个线程执行,但是cpu调度时间到了以后,第一个线程无论是否完成均程等待状态(若未执行完毕,数据放入寄存器中)下一线程得到的依旧是原始的公共数据。
用户级lock:保证同一时间只有一个线程在修改数据。(可以避免几个线程同时对公共原始数据进行修改,提高线程效率)
为公共数据Lock:一个线程修改后,释放,下一进程才可再次进行修改。
RLock(递归锁):在一个大锁中还要再包含子锁
1 importthreading, time2
3
4 defrun1():5 print("grab the first part data")6 lock.acquire()7 globalnum8 num += 1
9 lock.release()10 returnnum11
12
13 defrun2():14 print("grab the second part data")15 lock.acquire()16 globalnum217 num2 += 1
18 lock.release()19 returnnum220
21
22 defrun3():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 importthreading, time2
3 #信号量就是多个锁
4 defrun(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 importtime2 importthreading3
4 event =threading.Event()5 defLighter():6 count =07 event.set()8 whileTrue: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 += 1
21
22 defcar(name):23 whileTrue: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 importthreading,time2
3 importqueue4
5 q =queue.Queue()6 q.maxsize = 10
7
8 defProducer(name):9 count = 1
10 #for i in range(10):
11 whileTrue:12 q.put("骨头%s" %count) #%i)
13 print("生产了骨头",count)14 count += 1
15 time.sleep(2)16
17
18 defConsumer(name):19 whileTrue: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()