對Python多線程讀寫文件加鎖的實例詳解
Python的多線程在io方面比單線程還是有優(yōu)勢,但是在多線程開發(fā)時,少不了對文件的讀寫操作。在管理多個線程對同一文件的讀寫操作時,就少不了文件鎖了。
使用fcntl
在linux下,python的標(biāo)準(zhǔn)庫有現(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塊外,文件關(guān)閉,自動解鎖 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
小結(jié)
通過調(diào)用
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
對文件加鎖,如果有其他線程嘗試對test文件加鎖,會被阻塞。
當(dāng)線程執(zhí)行完畢的時候,鎖會自動釋放?;蛘咭部梢圆扇≈鲃拥姆绞浇怄i:調(diào)用
fcntl.flock(f.fileno(),fcntl.LOCK_UN)
函數(shù), 對文件test解鎖
使用線程鎖
當(dāng)多個線程共享一個數(shù)據(jù)的時候,必須要進行同步的控制,不然會出現(xiàn)不可預(yù)期的結(jié)果,即 “線程不安全”
線程同步能夠保證多個線程安全訪問競爭資源,最簡單的同步機制是引入互斥鎖。 互斥鎖為資源引入一個狀態(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í)行的單線程)
結(jié)果:
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
小結(jié)
當(dāng)一個線程調(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)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
python opencv 圖像處理之圖像算數(shù)運算及修改顏色空間
這篇文章主要介紹了python opencv 圖像處理之圖像算數(shù)運算及修改顏色空間,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下2022-08-08使用python求斐波那契數(shù)列中第n個數(shù)的值示例代碼
這篇文章主要給大家介紹了關(guān)于使用python求斐波那契數(shù)列中第n個數(shù)的值的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07python網(wǎng)絡(luò)編程學(xué)習(xí)筆記(二):socket建立網(wǎng)絡(luò)客戶端
看了這一節(jié),突然之間對python網(wǎng)絡(luò)編程學(xué)習(xí)筆記(1)中的一些不理解的問題有了認(rèn)識,至少明白了socket是怎么回事。這里關(guān)于socket的起源等問題就不做筆記記錄了,直接進入主題2014-06-06Python web開發(fā)之用Tornado框架制作簡易表白墻網(wǎng)站
這篇文章將用Python做Web開發(fā)。在Python當(dāng)中,WEB開發(fā)框架主要有三個,本文將利用Tornado框架做一個簡單的表白墻網(wǎng)站,感興趣的可以了解一下2022-02-02