1. 程式人生 > >python 執行緒相關筆記

python 執行緒相關筆記

執行緒 概念 執行緒又被稱之為輕量級程序 一個程序可擁有多個並行的執行緒 通俗的一點說就是一個程式有多個任務可以同時進行 一個程序中執行緒共享相同的記憶體單元/記憶體地址空間,可以訪問相同的成員 他們從同一個堆中分配物件,通訊、資料交換,同步操作 由於執行緒間的通訊是在同一地址空間進行的,所以,不需要額外的通訊機制 通過以上等優勢來提高Python的速度 程序與執行緒的區別 程序是系統進行資源分配和排程的獨立單位 程序在執行過程中擁有獨立的記憶體單元,多個執行緒共享,從而提高效率 執行緒是一個程序的實體,是CPU排程和分配的基本單位,從而提高程式執行效率 執行緒基本不擁有系統資源,只擁有執行時的一點必不可少的資源,但他與其他執行緒共享程序中的所有資源 使用多執行緒程式併發比較高 執行緒不能獨立執行,必須依賴程序 執行緒執行開銷小,但是不利於資源的管理保護 涉及到的模組 from threading import Thread import time 建立執行緒 引入模組 import time from threading import Thread 建立執行緒 建立一個執行函式 判斷是否主動執行 建立單個程序或者迴圈創建出多個執行緒 執行緒開始執行 例項1 from threading import Thread

import time

def xc(): print(“當前執行緒執行了”)

if name == ‘main’: for i in range(5): time.sleep(i) t = Thread(target=xc) t.start()

		例項2
			from threading import Thread

import time

def xc(num): print(“當前執行緒執行了%d”%num)

if name == ‘main’: for i in range(5): time.sleep(i) t = Thread(target=xc,args=(i+1,)) t.start()

		例項3
			from threading import Thread

import time

def sing(): for i in range(3): print(“我正在唱歌”)

t = Thread(target=sing) t.start()

	執行緒子類化
		將執行緒封裝到一個類中
		對資料進行封裝
		例項
			from threading import Thread

import time

class MyThread(Thread): def run(self): for i in range(10): time.sleep(2) string = "My name is “+self.name+” @ "+str(i) print(string)

m = MyThread()

m.start()

		例項2
			from threading import Thread

import time

class MyThread(Thread): def run(self): for i in range(10): time.sleep(2) string = "my name is “+self.name+” @ "+str(i) print(string)

for i in range(2): t = MyThread() t.start() 執行緒的狀態 阻塞 : 多執行緒的順序是不規律的,當執行到sleep語句的時候,執行緒將被阻塞 就緒 : 當sleep語句結束後,程式將要執行,這時執行緒處在就緒的狀態,等待排程,而執行緒排程會自行選擇一個執行緒執行 執行 : 排程處執行緒之後,程式執行,這個狀態就是執行狀態 執行時可能會出現阻塞事件 全域性變數 概念 在一個程序內,所有執行緒共享全域性變數 能夠在其他地方都不實用的環境中完成執行緒間的資料共享 缺點 : 執行緒可以對全域性變數隨意篡改,可能造成多執行緒間的全域性變數混亂 共享 線上程的操作中,全域性變數線上程中是共享的 例項1 from threading import Thread

import time

g_num = 100

def worker1(): global g_num for i in range(3): #重新定義了g_num 所以g_num如果不宣告為全域性變數 他就是區域性變數 g_num += 1 print(“worker1裡面的g_num等於%d”%g_num)

def worker2(): print(“worker2裡面的g_num等於%d”%g_num)

print(“主執行緒的g_num等於%d”%g_num)

t1 = Thread(target=worker1) t1.start()

time.sleep(2) print(’’)

t2 = Thread(target=worker2) t2.start()

					全域性變數共享
				實戰2(反例,傳參)
					from threading import Thread

import time

g_num = 100

def worker1(num): for i in range(3): num += 1 print(“worker1裡面的g_num等於%d”%num)

def worker2(num): print(“worker2裡面的g_num等於%d”%num)

print(“主執行緒的g_num等於%d”%g_num)

t1 = Thread(target=worker1,args=(g_num,)) t1.start()

time.sleep(2) print(’’)

t2 = Thread(target=worker2,args=(g_num,)) t2.start()

					這個以傳參的形式賦值,那麼就不屬於全域性變數,結果不共享
	執行緒同步
		概念
			當多執行緒同時修改某一個數據的時候,需要進行同步控制
			執行緒同步能夠保證多個執行緒安全訪問競爭資源,最簡單的同步機制是引入互斥鎖
			互斥鎖保證每次只有一個執行緒進行寫入操作,從而保證多執行緒的情況下資料的正確性
			某個執行緒要更改共享資料時,先將其鎖定,此時資源的狀態為“鎖定”,其他執行緒不能更改,直到該執行緒釋放資源,將資源的狀態變成“非鎖定”,其他執行緒才能再次鎖定該資源
			threading模組中定義了Lock類,可以方便的處理鎖定
		需要引入的模組
			from  threading   import  Thread
			from  threading  import  Lock
			import  time
		同步控制
			案例
				from threading import Thread

num = 0 def worker(): global num for i in range(2000000): num += 1

if name == ‘main’: for x in range(2): t = Thread(target=worker) t.start()

print(“這是執行緒的結果=======%d”%num) 多次變更,在兩萬六千次左右就會出現誤差 原因 資料進行運算時,先從記憶體中讀到暫存器中去,運算完畢後,再從暫存器中讀取到記憶體中來。 建立鎖 : mutex = threading.Lock() 鎖定 : mutex.acquire([blocking]) 如果設定blocking為True,則當前執行緒會阻塞,知道獲取這個鎖為止,如果沒有設定,預設為True 如果設定blocking為False,則當前執行緒不會阻塞 釋放 : mutex.release() 例項 from threading import Thread,Lock

import time

num = 0 #建立互斥所 mutex = Lock() def worker(): global num for i in range(10000000): mutexPlag = mutex.acquire(False) if mutexPlag: num += 1 mutex.release()

if name == ‘main’: for i in range(2): t = Thread(target=worker) t.start() t.join() print(num)

			死鎖現象  :  如果將執行緒鎖定,而沒有釋放,那麼就會出現死鎖現象