python多線程和GIL全局解釋器鎖


1、線程

    線程被稱為輕量級進程,是最小執行單元,系統調度的單位。線程切換需要的資源一般,效率一般。 

2、多線程

        在單個程序中同時運行多個線程完成不同的工作,稱為多線程

3、並發:

    操作系統同時執行幾個程序,這幾個程序都由一個cpu處理,但在一個時刻點上只有一個程序在cpu上處理

4、並行:

    操作系統同時執行2個程序,但是有兩個cpu,每個cpu處理一個程序,叫並行

5、串行: 

    是指的我們從事某項工作是一個步驟一個步驟去實施 
 

一、多線程

#python3是假的多線程,它不是真真正正的並行,其實就是串行,只不過利用了cpu上下文的切換而已
 1 mport threading
 2 import time
 3 # def test1():
 4 #     for i in range(10):
 5 #         time.sleep(1)             #睡1s
 6 #         print('test1=========>%s' % i)
 7 #
 8 #
 9 # def test2():
10 #     for i in range(10):
11 #         time.sleep(1)
12 #         print('test2=========>%s' % i)
13 #
14 # t1 = threading.Thread(target=test1)    #定義一個線程  target=函數名
15 # t2 = threading.Thread(target=test2)
16 # t1.start()        #開啟線程
17 # t2.start()
18 # test1()
19 # test2()

# 多線程是無序的,並發的
因為在啟動一個線程時,線程不會立即執行,而是等待cpu的資源調度。
1 # def test1(n):
2 #     time.sleep(1)
3 #     print('task', n)
4 # for i in range(10):
5 #     t = threading.Thread(target=test1,args=('t-%s' % i,))  #args= 后接輸出結果  末尾必須加 “ , ” 號
6 #     t.start()
 
#計算並發所用的時間
 1  
 2 # import threading
 3 # import time
 4 # def dest(n):
 5 #     time.sleep(1)
 6 #     print('this is running====>%s' %n)
 7 # l = []     #定義一個空列表
 8 # start = time.time()     #開始的時間
 9 # for i in range(10):        #10個進程
10 #     t = threading.Thread(target=dest,args=(i,))    
11 #     t.start()
12 #     l.append(t)      #把線程執行時間加入到列表
13 # for g in l:       
14 #     g.join()            #等待全部線程執行完畢
15 # end = time.time()            #執行結束時間
16 # print('time',(end-start))   #執行結束時間 - 開始執行的時間
 
 1 import threading
 2 import time
 3 def test1(n):
 4     time.sleep(1)
 5     print('test1====>%s' %n)
 6 def test2(n):
 7     time.sleep(2)
 8     print('test2====>%s' %n)
 9 start = time.time()
10 l = []
11 t1 =  threading.Thread(target=test1,args=(1,))
12 t2 = threading.Thread(target=test2,args=(2,))
13 t1.start()
14 t2.start()
15 l.append(t1)
16 l.append(t2)
17 for i in l:
18     i.join()
19 end = time.time()
20 print('time',(end - start))
View Code
 
#多線程共享全局變量
 1 # g_num = 0
 2 # def update():
 3 #     global g_num    #global聲明全局變量
 4 #     for i in range(10):
 5 #         g_num += 1
 6 #
 7 # def reader():
 8 #     global g_num
 9 #     print(g_num)
10 #
11 # t1 = threading.Thread(target=update)
12 # t2 = threading.Thread(target=reader)
13 # t1.start()
14 # t2.start()
15  

二、GIL全局解釋器鎖

        只有獲得GIL鎖的線程才能真正在cpu上運行。所以,多線程在python中只能交替執行,即使100個線程跑在100核cpu上,也只能用到1核。
 1  
 2 # import threading
 3 # global_num = 0
 4 # def test1():
 5 #     global global_num        #global聲明全局變量
 6 #     for i in range(1000000):
 7 #         global_num += 1
 8 #     print("test1", global_num,threading.current_thread())
 9 #
10 # def test2():
11 #     global global_num
12 #     for i in range(1000000):
13 #         global_num += 1
14 #     print("test2", global_num,threading.current_thread())
15 # t1 = threading.Thread(target=test1)
16 # t2 = threading.Thread(target=test2)
17 # t1.start()
18 # t2.start()
19 # print(global_num)
結果說明:每次執行結果都不一樣,原因是python從上往下執行,主線程走的快,當主線程走到最后print打印結果的時候,test1 test2的count++還在繼續執行,所以第一行打印出來的是它們在執行count++過程中的某一個值,至於test1和test2的值不是100w和200w,因為cpu沒有足夠的時間去進行count++就釋放鎖提交了
 

#互斥鎖

以上出現的結果是隨機的,並非我們想要的,所以要加入互斥鎖。
互斥鎖:
常用來防止兩個進程或線程同一時刻訪問相同的共享資源, 如果一個線程鎖定了一個互斥量,在它解除鎖定之前沒有其他線程可以鎖定這個互斥量。
 1 import threading
 2 import time
 3 global_num = 0
 4  
 5 lock = threading.Lock()           #互斥鎖
 6  
 7 def test1():
 8     global global_num
 9     lock.acquire()
10     for i in range(1000000):
11         global_num += 1
12     lock.release()
13     print("test1", global_num)
14  
15  
16 def test2():
17     global global_num
18     lock.acquire()
19     for i in range(1000000):
20         global_num += 1
21     lock.release()
22     print("test2", global_num)
23  
24 t1 = threading.Thread(target=test1)
25 t2 = threading.Thread(target=test2)
26 start_time = time.time()
27  
28 t1.start()
29 t2.start()
30 t1.join()
31 t2.join()
32 print(global_num)
加上互斥鎖之后,test1線程執行完才釋放鎖提交,讓test2線程拿到共享資源繼續執行,要想結果是200w,就必須是主線程等子線程執行完之后才執行print。
 
#只要在進行耗時的IO操作的時候,能釋放GIL,所以只要在IO密集型的代碼里,用多線程就很合適
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM