對(duì)Python多線程讀寫文件加鎖的實(shí)例詳解
Python的多線程在io方面比單線程還是有優(yōu)勢(shì),但是在多線程開發(fā)時(shí),少不了對(duì)文件的讀寫操作。在管理多個(gè)線程對(duì)同一文件的讀寫操作時(shí),就少不了文件鎖了。
使用fcntl
在linux下,python的標(biāo)準(zhǔn)庫(kù)有現(xiàn)成的文件鎖,來(lái)自于fcntl模塊。這個(gè)模塊提供了unix系統(tǒng)fcntl()和ioctl()的接口。
對(duì)于文件鎖的操作,主要需要使用 fcntl.flock(fd, operation)這個(gè)函數(shù)。
其中,參數(shù) fd 表示文件描述符;參數(shù) operation 指定要進(jìn)行的鎖操作,該參數(shù)的取值有如下幾種:
LOCK_SH:表示要?jiǎng)?chuàng)建一個(gè)共享鎖,在任意時(shí)間內(nèi),一個(gè)文件的共享鎖可以被多個(gè)進(jìn)程擁有
LOCK_EX:表示創(chuàng)建一個(gè)排他鎖,在任意時(shí)間內(nèi),一個(gè)文件的排他鎖只能被一個(gè)進(jìn)程擁有
LOCK_UN:表示刪除該進(jìn)程創(chuàng)建的鎖
LOCK_MAND:它主要是用于共享模式強(qiáng)制鎖,它可以與 LOCK_READ 或者 LOCK_WRITE聯(lián)合起來(lái)使用,從而表示是否允許并發(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)閉,自動(dòng)解鎖
print "{0} exit".format(id)
for i in range(5):
myThread = threading.Thread(target=writetoTxt, args=("test.txt",))
myThread.start()
代碼運(yùn)行期間,控制臺(tái)將依次打印哪個(gè)線程獲得了鎖,在對(duì)文件進(jìn)行讀寫。
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é)
通過(guò)調(diào)用
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
對(duì)文件加鎖,如果有其他線程嘗試對(duì)test文件加鎖,會(huì)被阻塞。
當(dāng)線程執(zhí)行完畢的時(shí)候,鎖會(huì)自動(dòng)釋放?;蛘咭部梢圆扇≈鲃?dòng)的方式解鎖:調(diào)用
fcntl.flock(f.fileno(),fcntl.LOCK_UN)
函數(shù), 對(duì)文件test解鎖
使用線程鎖
當(dāng)多個(gè)線程共享一個(gè)數(shù)據(jù)的時(shí)候,必須要進(jìn)行同步的控制,不然會(huì)出現(xiàn)不可預(yù)期的結(jié)果,即 “線程不安全”
線程同步能夠保證多個(gè)線程安全訪問(wèn)競(jìng)爭(zhēng)資源,最簡(jiǎn)單的同步機(jī)制是引入互斥鎖。 互斥鎖為資源引入一個(gè)狀態(tài):鎖定/非鎖定。 某個(gè)線程要更改共享數(shù)據(jù)時(shí),先將其鎖定,此時(shí)資源的狀態(tài)為“鎖定”,其他線程不能更改; 直到該線程釋放資源,將資源的狀態(tài)變成“非鎖定”,其他的線程才能再次鎖定該資源。 互斥鎖保證了每次只有一個(gè)線程進(jìn)行寫入操作,從而保證了多線程情況下數(shù)據(jù)的正確性。
threading模塊中定義了Lock類,可以方便的處理鎖定:
#創(chuàng)建鎖 mutex = threading.Lock() #鎖定 mutex.acquire([timeout]) #解鎖 mutex.release()
Demo
使用互斥鎖實(shí)現(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ì)上是一個(gè)順序執(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)一個(gè)線程調(diào)用鎖的acquire()方法獲得鎖時(shí),鎖就進(jìn)入“l(fā)ocked”狀態(tài)。每次只有一個(gè)線程可以獲得鎖。如果此時(shí)另一個(gè)線程試圖獲得這個(gè)鎖,該線程就會(huì)變?yōu)椤癰locked”狀態(tài),稱為“同步阻塞”。
直到擁有鎖的線程調(diào)用鎖的release()方法釋放鎖之后,鎖進(jìn)入“unlocked”狀態(tài)。線程調(diào)度程序從處于同步阻塞狀態(tài)的線程中選擇一個(gè)來(lái)獲得鎖,并使得該線程進(jìn)入運(yùn)行(running)狀態(tài)。
以上這篇對(duì)Python多線程讀寫文件加鎖的實(shí)例詳解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
新版pycharm配置運(yùn)行參數(shù)的教程/pycharm2023
這篇文章主要介紹了新版pycharm配置運(yùn)行參數(shù)的教程/pycharm2023,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Flask SocketIO實(shí)現(xiàn)動(dòng)態(tài)繪圖的示例詳解
Flask-SocketIO 是基于 Flask 的一個(gè)擴(kuò)展,用于簡(jiǎn)化在 Flask 應(yīng)用中集成 WebSocket 功能,本文主要介紹了Flask SocketIO如何實(shí)現(xiàn)動(dòng)態(tài)繪圖,需要的可以參考下2023-11-11
Flask框架學(xué)習(xí)筆記之表單基礎(chǔ)介紹與表單提交方式
這篇文章主要介紹了Flask框架學(xué)習(xí)筆記之表單基礎(chǔ)介紹與表單提交方式,結(jié)合實(shí)例形式分析了flask框架中表單的基本功能、定義、用法及表單提交的get、post方式使用技巧,需要的朋友可以參考下2019-08-08
python關(guān)于多值參數(shù)的實(shí)例詳解
在本篇內(nèi)容里小編給大家整理了一篇關(guān)于python關(guān)于多值參數(shù)的實(shí)例詳解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2021-07-07
Python?Traceback(most?recent?call?last)報(bào)錯(cuò)信息:示例解讀
這篇文章主要介紹了Python?Traceback(most?recent?call?last)報(bào)錯(cuò)信息:示例解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Python實(shí)現(xiàn)人臉識(shí)別并進(jìn)行視頻跟蹤打碼
這篇文章主要為大家詳細(xì)介紹了如何利用Python實(shí)現(xiàn)人臉識(shí)別并進(jìn)行視頻跟蹤打碼效果,羞羞的畫面統(tǒng)統(tǒng)打上馬賽克,感興趣的小伙伴可以了解一下2023-03-03

