Python多執行緒讀寫檔案加鎖

2021-09-01 02:19:34 字數 2944 閱讀 9192

python的多執行緒在io方面比單執行緒還是有優勢,但是在多執行緒開發時,少不了對檔案的讀寫操作。在管理多個執行緒對同一檔案的讀寫操作時,就少不了檔案鎖了。

在linux下,python的標準庫有現成的檔案鎖,來自於fcntl模組。這個模組提供了unix系統fcntl()和ioctl()的介面。

對於檔案鎖的操作,主要需要使用 fcntl.flock(fd, operation)這個函式。

其中,引數 fd 表示檔案描述符;引數 operation 指定要進行的鎖操作,該引數的取值有如下幾種:

import fcntl

import threading

import time

def writetotxt(txtfile):

id = threading.currentthread().getname()

with open(txtfile, 'a') as f:

fcntl.flock(f.fileno(), fcntl.lock_ex) #加鎖

print " acquire lock".format(id)

f.write("write from \r\n".format(id))

time.sleep(3)

# 在with塊外,檔案關閉,自動解鎖

print " exit".format(id)

for i in range(5):

mythread = threading.thread(target=writetotxt, args=("test.txt",))

mythread.start()

**執行期間,控制台將依次列印哪個執行緒獲得了鎖,在對檔案進行讀寫。

thread-1 acquire lock

thread-1 exit

thread-2 acquire lock

thread-2 exit

thread-3 acquire lock

thread-3 exit

thread-5 acquire lock

thread-5 exit

thread-4 acquire lock

thread-4 exit

通過呼叫

fcntl.flock(f.fileno(), fcntl.lock_ex)
對檔案加鎖,如果有其他執行緒嘗試對test檔案加鎖,會被阻塞。

當執行緒執行完畢的時候,鎖會自動釋放。或者也可以採取主動的方式解鎖:呼叫

fcntl.flock(f.fileno(),fcntl.lock_un)
函式, 對檔案test解鎖

當多個執行緒共享乙個資料的時候,必須要進行同步的控制,不然會出現不可預期的結果,即 「執行緒不安全」

執行緒同步能夠保證多個執行緒安全訪問競爭資源,最簡單的同步機制是引入互斥鎖。

互斥鎖為資源引入乙個狀態:鎖定/非鎖定。

某個執行緒要更改共享資料時,先將其鎖定,此時資源的狀態為「鎖定」,其他執行緒不能更改;

直到該執行緒釋放資源,將資源的狀態變成「非鎖定」,其他的執行緒才能再次鎖定該資源。

互斥鎖保證了每次只有乙個執行緒進行寫入操作,從而保證了多執行緒情況下資料的正確性。

threading模組中定義了lock類,可以方便的處理鎖定:

#建立鎖

mutex = threading.lock()

#鎖定mutex.acquire([timeout])

#解鎖mutex.release()

使用互斥鎖實現上面的例子的**如下:

import threading

import time

def writetotxt(txtfile):

id = threading.currentthread().getname()

mutex.acquire(10)

with open(txtfile, 'a') as f:

print "thread acquire lock".format(id)

f.write("write from thread \r\n".format(id))

time.sleep(3)

mutex.release()

print "thread exit".format(id)

mutex = threading.lock()

for i in range(5):

mythread = threading.thread(target=writetotxt, args=("test.txt",))

mythread.start()

(上述**本質上是乙個順序執行的單執行緒)

結果:

thread thread-1 acquire lock

thread thread-1 exit

thread thread-2 acquire lock

thread thread-2 exit

thread thread-3 acquire lock

thread thread-3 exit

thread thread-4 acquire lock

thread thread-4 exit

thread thread-5 acquire lock

thread thread-5 exit

當乙個執行緒呼叫鎖的acquire()方法獲得鎖時,鎖就進入「locked」狀態。每次只有乙個執行緒可以獲得鎖。如果此時另乙個執行緒試圖獲得這個鎖,該執行緒就會變為「blocked」狀態,稱為「同步阻塞」。

直到擁有鎖的執行緒呼叫鎖的release()方法釋放鎖之後,鎖進入「unlocked」狀態。執行緒排程程式從處於同步阻塞狀態的執行緒中選擇乙個來獲得鎖,並使得該執行緒進入執行(running)狀態。

Python 多執行緒不加鎖分塊讀取檔案

多執行緒讀取或寫入,一般會涉及到同步的問題,否則產生的結果是無法預期的。那麼在讀取乙個檔案的時候,我們可以通過加鎖,但讀不像寫操作,會導致檔案錯誤,另外鎖操作是有一定的耗時。因此通過檔案分塊,可以比較有效的解決多執行緒讀問題,之前看到有人寫的分塊操作,比較複雜,需要實現建立好執行緒以及所讀取塊資訊,...

Python多執行緒程式設計之多執行緒加鎖

python語言本身是支援多執行緒的,不像php語言。下面的例子是多個執行緒做同一批任務,任務總是有task num個,每次執行緒做乙個任務 print 做完後繼續取任務,直到所有任務完成為止。1 coding utf 8 2import threading 34 start task 0 5 ta...

python 多執行緒 thread 加鎖(二)

thread.start new thread function,args kwargs 函式原型,其中function引數是你將要呼叫的執行緒函式名稱沒有括號 args是講傳遞給你的執行緒函式的引數,他必須是個tuple型別 而kwargs是可選的引數,如果沒有引數,也一定是 import thr...