1. 程式人生 > >Python中的多線程

Python中的多線程

info print pre lock map __main__ color 開啟 self

1、什麽是線程

  進程其實不是一個執行單位,進程是一個資源單位

  每個進程內自帶一個線程,線程才是CPU上的執行單位

  

如果把操作系統比喻為一座工廠

  在工廠內每造出一個車間===》啟動一個進程

  每個車間內至少有一條流水線===》每個進程內至少有一個線程

線程==》單指代碼的執行過程

進程==》資源的申請與銷毀的過程

2、進程VS線程

  1)內存共享or隔離

    多個進程內存空間彼此隔離

    同一進程下的多個線程共享該進程內的數據

  2)創建速度

    造線程的速度要遠遠快於造進程

一、開啟線程的兩種方式(重點)


方式一:導入Thread模塊

1
from
threading import Thread 2 import time 3 5 def task(name): 6 print(%s is running %name) 7 time.sleep(3) 8 print(%s is done %name) 9 if __name__ == __main__: 10 t=Thread(target=task,args=(子線程,)) 11 t.start() 12 print()


方式二:創建類繼承Thread

1
from threading import
Thread 2 import time 3 4 6 # class Mythread(Thread): 7 # def run(self): 8 # print(‘%s is running‘ %self.name) 9 # time.sleep(3) 10 # print(‘%s is done‘ %self.name) 11 # 12 # if __name__ == ‘__main__‘: 13 # t=Mythread() 14 # t.start() 15 # print(‘主‘)

二、線程VS進程(重點)

 1 # from threading import Thread
 2 # from multiprocessing import Process
 3 # import time
 4 #
 5 # def task(name):
 6 #     print(‘%s is running‘ %name)
 7 #     time.sleep(3)
 8 #     print(‘%s is done‘ %name)
 9 #
10 # if __name__ == ‘__main__‘:
11 #     t=Thread(target=task,args=(‘子線程‘,))
12 #     # t=Process(target=task,args=(‘子進程‘,))
13 #     t.start()
14 #     print(‘主‘)

線程運行結果:

技術分享圖片

進程運行結果:

技術分享圖片

2)同一進程下的多個線程共享該進程內的數據(了解知識點)

技術分享圖片
 1 # from threading import Thread
 2 # import time
 3 #
 4 # x=100
 5 # def task():
 6 #     global x
 7 #     x=0
 8 #
 9 # if __name__ == ‘__main__‘:
10 #     t=Thread(target=task,)
11 #     t.start()
12 #     # time.sleep(3)
13 #     t.join()
14 #     print(‘主‘,x)
View Code

3)查看pid(了解知識點)

註意:一個進程中的子線程pid相同

技術分享圖片
 1 from threading import Thread
 2 import time,os
 3 
 4 def task():
 5     print(os.getpid())
 6 
 7 if __name__ == __main__:
 8     t=Thread(target=task,)
 9     t.start()
10     print(,os.getpid())
View Code

三、線程對象的其他方法和屬性(熟悉知識點)

1)主進程等子進程是因為主進程要給子進程收屍

2)進程必須等待其內部所有線程都運行完畢才結束

技術分享圖片
 1 # from threading import Thread
 2 # import time
 3 #
 4 # def task(name):
 5 #     print(‘%s is running‘ %name)
 6 #     time.sleep(3)
 7 #     print(‘%s is done‘ %name)
 8 # if __name__ == ‘__main__‘:
 9 #     t=Thread(target=task,args=(‘子線程‘,))
10 #     t.start()
11 #     print(‘主‘)
12 #
View Code

技術分享圖片
 1 from threading import Thread,current_thread,active_count,enumerate
 2 import time
 3 
 4 
 5 def task():
 6     print(%s is running % current_thread().name)
 7     time.sleep(3)
 8     print(%s is done % current_thread().name)
 9 
10 
11 if __name__ == __main__:
12     t = Thread(target=task,name=xxx)
13     t.start()
14     # t.join()
15     # print(t.is_alive())
16     # print(t.getName())
17     # print(t.name)
18     # print(‘主‘,active_count())
19     # print(enumerate())
20 
21     # t.join()
22     current_thread().setName(主線程)
23     print(,current_thread().name)
View Code

四、守護線程(熟悉知識點)

守護線程(daemon)會在本進程內所有非守護的線程都死掉了才跟著死

即:

  守護線程其實守護的是整個進程的運行周期(進程內所有的非守護線程都運行完畢)

技術分享圖片
 1 # from threading import Thread,current_thread
 2 # import time
 3 #
 4 #
 5 # def task():
 6 #     print(‘%s is running‘ % current_thread().name)
 7 #     time.sleep(3)
 8 #     print(‘%s is done‘ % current_thread().name)
 9 #
10 #
11 # if __name__ == ‘__main__‘:
12 #     t = Thread(target=task,name=‘守護線程‘)
13 #     t.daemon=True
14 #     t.start()
15 #     print(‘主‘)
守護進程 技術分享圖片
 1 from threading import Thread
 2 import time
 3 def foo():
 4     print(123)
 5     time.sleep(3)
 6     print("end123")
 7 
 8 def bar():
 9     print(456)
10     time.sleep(1)
11     print("end456")
12 
13 
14 t1=Thread(target=foo)
15 t2=Thread(target=bar)
16 
17 t1.daemon=True
18 t1.start()
19 t2.start()
20 print("main-------")
21 
22 ‘‘‘
23 123
24 456
25 main-------
26 end456
27 
28 ‘‘‘
較迷惑人的守護進程

五、互斥鎖(熟悉知識點)

技術分享圖片
 1 from threading import Thread,Lock
 2 import time
 3 
 4 mutex=Lock()
 5 
 6 x=100
 7 def task():
 8     global x
 9     # mutex.acquire()
10     temp=x
11     time.sleep(0.1)
12     x=temp-1
13     # mutex.release()
14 
15 if __name__ == __main__:
16     t_l=[]
17     start=time.time()
18     for i in range(100):
19         t=Thread(target=task)
20         t_l.append(t)
21         t.start()
22 
23     for t in t_l:
24         t.join()
25 
26     stop=time.time()
27     print(x,stop-start)
互斥鎖

六、死鎖現象與遞歸鎖(熟悉知識點)

  如果用Lock(互斥鎖),會發生死鎖現象

  遞歸鎖本質是一把鎖,可連續acqruie,但只有其上的計數為0時其他線程才可對其調用

技術分享圖片
 1 from threading import Thread,Lock,active_count,RLock
 2 import time
 3 
 4 # mutexA=Lock()
 5 # mutexB=Lock()
 6 obj=RLock() #遞歸鎖的特點:可以連續的acquire
 7 mutexA=obj
 8 mutexB=obj
 9 
10 class Mythread(Thread):
11     def run(self):
12         self.f1()
13         self.f2()
14 
15     def f1(self):
16         mutexA.acquire()
17         print(%s 拿到A鎖 %self.name)
18 
19         mutexB.acquire()
20         print(%s 拿到B鎖 %self.name)
21         mutexB.release()
22 
23         mutexA.release()
24 
25     def f2(self):
26         mutexB.acquire()
27         print(%s 拿到B鎖 %self.name)
28         time.sleep(1)
29 
30         mutexA.acquire()
31         print(%s 拿到A鎖 %self.name)
32         mutexA.release()
33 
34         mutexB.release()
35 
36 if __name__ == __main__:
37     for i in range(10):
38         t=Mythread()
39         t.start()
40     # print(active_count())
View Code

七、信號量(熟悉知識點)

  信號量本質上還是鎖,但區別信號量是控制同一時刻並發執行的任務數

技術分享圖片
 1 from threading import Thread,Semaphore,current_thread
 2 import time,random
 3 
 4 sm=Semaphore(5)
 5 
 6 def task():
 7     with sm:
 8         print(%s 正在上廁所 %current_thread().name)
 9         time.sleep(random.randint(1,4))
10 
11 
12 if __name__ == __main__:
13     for i in range(20):
14         t=Thread(target=task)
15         t.start()
信號量

Python中的多線程