溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python中怎么利用多線程讀寫文件并加鎖

發(fā)布時間:2021-06-15 17:10:33 來源:億速云 閱讀:371 作者:Leah 欄目:開發(fā)技術

這篇文章給大家介紹Python中怎么利用多線程讀寫文件并加鎖,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

使用fcntl

在linux下,python的標準庫有現(xiàn)成的文件鎖,來自于fcntl模塊。這個模塊提供了unix系統(tǒng)fcntl()和ioctl()的接口。

對于文件鎖的操作,主要需要使用 fcntl.flock(fd, operation)這個函數(shù)。

其中,參數(shù) fd 表示文件描述符;參數(shù) operation 指定要進行的鎖操作,該參數(shù)的取值有如下幾種:

LOCK_SH:表示要創(chuàng)建一個共享鎖,在任意時間內(nèi),一個文件的共享鎖可以被多個進程擁有

LOCK_EX:表示創(chuàng)建一個排他鎖,在任意時間內(nèi),一個文件的排他鎖只能被一個進程擁有

LOCK_UN:表示刪除該進程創(chuàng)建的鎖

LOCK_MAND:它主要是用于共享模式強制鎖,它可以與 LOCK_READ 或者 LOCK_WRITE聯(lián)合起來使用,從而表示是否允許并發(fā)的讀操作或者并發(fā)的寫操作

demo

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 "{0} acquire lock".format(id)
  f.write("write from {0} \r\n".format(id))
  time.sleep(3)
 # 在with塊外,文件關閉,自動解鎖
 print "{0} 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

小結

通過調(diào)用

fcntl.flock(f.fileno(), fcntl.LOCK_EX)

對文件加鎖,如果有其他線程嘗試對test文件加鎖,會被阻塞。

當線程執(zhí)行完畢的時候,鎖會自動釋放?;蛘咭部梢圆扇≈鲃拥姆绞浇怄i:調(diào)用

fcntl.flock(f.fileno(),fcntl.LOCK_UN)

函數(shù), 對文件test解鎖

使用線程鎖

當多個線程共享一個數(shù)據(jù)的時候,必須要進行同步的控制,不然會出現(xiàn)不可預期的結果,即 “線程不安全”

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

互斥鎖為資源引入一個狀態(tài):鎖定/非鎖定。

某個線程要更改共享數(shù)據(jù)時,先將其鎖定,此時資源的狀態(tài)為“鎖定”,其他線程不能更改;

直到該線程釋放資源,將資源的狀態(tài)變成“非鎖定”,其他的線程才能再次鎖定該資源。

互斥鎖保證了每次只有一個線程進行寫入操作,從而保證了多線程情況下數(shù)據(jù)的正確性。

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

#創(chuàng)建鎖
mutex = threading.Lock()
#鎖定
mutex.acquire([timeout])
#解鎖
mutex.release()

Demo

使用互斥鎖實現(xiàn)上面的例子的代碼如下:

import threading
import time
 
def writetoTxt(txtFile):
 id = threading.currentThread().getName()
 mutex.acquire(10)
 with open(txtFile, 'a') as f:
  print "Thread {0} acquire lock".format(id)
  f.write("write from thread {0} \r\n".format(id))
  time.sleep(3)
 mutex.release()
 print "Thread {0} exit".format(id)
 
 
mutex = threading.Lock()
 
for i in range(5):
 myThread = threading.Thread(target=writetoTxt, args=("test.txt",))
 myThread.start()

(上述代碼本質(zhì)上是一個順序執(zhí)行的單線程)

結果:

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

小結

當一個線程調(diào)用鎖的acquire()方法獲得鎖時,鎖就進入“l(fā)ocked”狀態(tài)。每次只有一個線程可以獲得鎖。如果此時另一個線程試圖獲得這個鎖,該線程就會變?yōu)椤癰locked”狀態(tài),稱為“同步阻塞”。

直到擁有鎖的線程調(diào)用鎖的release()方法釋放鎖之后,鎖進入“unlocked”狀態(tài)。線程調(diào)度程序從處于同步阻塞狀態(tài)的線程中選擇一個來獲得鎖,并使得該線程進入運行(running)狀態(tài)。

關于Python中怎么利用多線程讀寫文件并加鎖就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI