1. 程式人生 > >python之執行緒相關操作

python之執行緒相關操作

1.執行緒: 一個程序可以有多個執行緒,共享一個程序的資源;

2.程序執行緒的區別:

   程序是資源分配的最小單位,執行緒是程式執行的最小單位

3.python中執行緒模組threading, 提供的類: Thread, Lock, Rlock, Semaphore, Event, 等等

4.執行緒的建立方式

# 第一種
# from threading import Thread
# def f1(s):
#     print('我是%s' % s)
# def f2(s):
#     print('我是%s' % s)
# 
# if __name__ == '__main__':
# t = Thread(target=f1, args=(1,)) # t1 = Thread(target=f1, args=(2,)) # t.start() # t1.start() # print('我是主執行緒') # 第二種 from threading import Thread class MyThread(Thread): def __init__(self, name): super().__init__() self.name = name def run(self):
print('%s今天還是不能皮' % self.name) if __name__ == '__main__': t = MyThread('Jerry') t.start() print('主執行緒')

6.檢視執行緒的程序id(同進程檢視方式一樣)

import os
from threading import Thread
def f1(n):
    print('1號', os.getpid())
    print('%s號執行緒任務' % n)
def f2(n):
    print('2號', os.getpid())
    print
('%s號執行緒任務' % n) if __name__ == '__main__': t1 = Thread(target=f1, args=(1,)) t2 = Thread(target=f2, args=(2,)) t1.start() t2.start() print('主執行緒', os.getpid()) print('主執行緒')

7. 在程序之間資料是空間隔離的, 而線上程中是資料共享的

import time
from threading import Thread

#  通過對全域性變數的修改來驗證執行緒之間是資料共享的, 共享同一程序中的資料
num = 100
def f1():
    time.sleep(3)
    global  num
    num = 3
    print('子執行緒的num', num)

if __name__ == '__main__':
    t = Thread(target=f1)
    t.start()
    t.join() # 等待子執行緒執行結束才繼續向下執行
    print('主執行緒的num', num)

8.多程序和多執行緒的效率對比

對於io密集型的, 多執行緒的時間較快

def f1():
    time.sleep(1)  #io密集型
    
if __name__ == '__main__':
    # 檢視一下20個執行緒執行20個任務的執行時間
    t_s_time = time.time()
    t_list = []
    for i in range(5):
        t = Thread(target=f1,)
        t.start()
        t_list.append(t)
    [tt.join() for tt in t_list]
    t_e_time = time.time()
    t_dif_time = t_e_time - t_s_time
    # 檢視一下20個程序執行同樣的任務的執行時間
    p_s_time = time.time()
    p_list = []
    for i in range(5):
        p = Process(target=f1,)
        p.start()
        p_list.append(p)
    [pp.join() for pp in p_list]
    p_e_time = time.time()
    p_dif_time = p_e_time - p_s_time
    print('多執行緒的執行時間:', t_dif_time)
    print('多jincheng的執行時間:', p_dif_time)

計算型:

import time
from threading import Thread
from multiprocessing import Process

def f1():
    # 計算型:
    n = 10
    for i in range(10000000):
        n = n + i
if __name__ == '__main__':
    # 檢視一下20個執行緒執行20個任務的執行時間
    t_s_time = time.time()
    t_list = []
    for i in range(5):
        t = Thread(target=f1,)
        t.start()
        t_list.append(t)
    [tt.join() for tt in t_list]
    t_e_time = time.time()
    t_dif_time = t_e_time - t_s_time
    # 檢視一下20個程序執行同樣的任務的執行時間
    p_s_time = time.time()
    p_list = []
    for i in range(5):
        p = Process(target=f1,)
        p.start()
        p_list.append(p)
    [pp.join() for pp in p_list]
    p_e_time = time.time()
    p_dif_time = p_e_time - p_s_time
    print('多執行緒的執行時間:', t_dif_time)
    print('多jincheng的執行時間:', p_dif_time)

 

 9.鎖,同步,互斥鎖 為了保護多線成中資料的完整性和執行緒間狀態的同步.(同進程的鎖一樣)

 線上程鎖中, 會產生死鎖現象. 同時搶鎖

import time
from threading import Thread, Lock, RLock
def f1(locA, locB):
    # print('xxxx')
    # time.sleep(0.1)
    locA.acquire()
    print('f1>>1號搶到了A鎖')

    time.sleep(1)
    locB.acquire()
    print('f1>>1號搶到了B鎖')
    locB.release()

    locA.release()
def f2(locA, locB):
    print('22222')
    time.sleep(0.1)
    locB.acquire()
    print('f2>>2號搶到了B鎖')
    locA.acquire()
    time.sleep(1)
    print('f2>>2號搶到了A鎖')
    locA.release()
    locB.release()
if __name__ == '__main__':
    locA = Lock()
    locB = Lock()
    t1 = Thread(target=f1, args=(locA, locB))
    t2 = Thread(target=f2, args=(locA, locB))
    t1.start()
    t2.start()

  遞迴鎖解決了 死鎖現象

import time
from threading import Thread, Lock, RLock

def f1(locA, locB):
    print('xxxxx')
    time.sleep(0.1)
    locA.acquire()
    print('f1>>>1號搶到了A鎖')
    time.sleep(1)
    locB.acquire()
    print('f1>>>2號搶到了B鎖')
    locB.release()
    locA.release()
def f2(locA, locB):
    print('22222')
    time.sleep(0.1)
    locB.acquire()
    print('f2>>>1號搶到了A鎖')
    time.sleep(1)
    locA.acquire()
    print('f2>>>2號搶到了B鎖')
    locA.release()
    locB.release()
if __name__ == '__main__':
    locA = locB = RLock()
    t1 = Thread(target=f1, args=(locA, locB))
    t2 = Thread(target=f2, args=(locB, locA))
    t1.start()
    t2.start()

10.多執行緒的程式不結束 和 多程序的程式不結束的區別

守護程序:主程序程式碼執行執行結束,守護程序隨之結束
守護執行緒:守護執行緒會等待所有非守護執行緒執行結束才結束
import time
from threading import Thread
from multiprocessing import Process


# 守護程序:主程序程式碼執行執行結束,守護程序隨之結束
# 守護執行緒:守護執行緒會等待所有非守護執行緒執行結束才結束
def f1():
    time.sleep(2)
    print('一號執行緒')

def f2():
    time.sleep(3)
    print('二號執行緒')
def f3():
    time.sleep(2)
    print('一號程序')

def f4():
    time.sleep(3)
    print('二號程序')
if __name__ == '__main__':
    # t1 = Thread(target=f1,)
    # t2 = Thread(target=f2,)
    # # t1.daemon = True  #  等非守護執行緒結束,守護執行緒才會結束 結果:  主執行緒結束  一號執行緒  二號執行緒
    # t2.daemon = True # 結果: 主執行緒結束      一號執行緒
    # t1.start()
    # t2.start()
    # print('主執行緒結束')
    p1 = Process(target=f3,)
    p2 = Process(target=f4,)
    # p1.daemon = True # 結果: 主程序   二號執行緒
    p2.daemon= True # 結果: 主程序   一號執行緒
    p1.start()
    p2.start()
    print('主程序')

11. GIL鎖 :  cpython直譯器上的一把互斥鎖, Python直譯器由於設計時有GIL全域性鎖,導致了多執行緒無法利用多核

Python雖然不能利用多執行緒實現多核任務,但可以通過多程序實現多核任務。多個Python程序有各自獨立的GIL鎖,互不影響。