Python中的多線程

一、什麼是線程併發

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

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

  

若是把操做系統比喻爲一座工廠ide

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

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

線程==》單指代碼的執行過程操作系統

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

 

二、進程VS線程3d

  1)內存共享or隔離code

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

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

  2)建立速度

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

 

1、開啓線程的兩種方式(重點)

 
 
方式一:導入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('主')

2、線程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

 

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

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

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

守護線程(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 '''
較迷惑人的守護進程

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

 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)
互斥鎖

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

  若是用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

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

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

 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()
信號量
相關文章
相關標籤/搜索