- 文件鎖(fcntl)
- fcntl這個模塊是Python自帶的,但Windows沒有,可以手工下載fcntl.py文件,然后保存到python的Lib目錄下
- 鎖類型(fcntl.flock函數的第二個參數)
-
LOCK_SH: 表示要創建一個共享鎖,所有進程沒有寫訪問權限,即使是加鎖進程也沒有。所有進程有讀訪問權限,在任意時間內,一個文件的共享鎖可以被多個進程擁有。
LOCK_EX: 表示創建一個排他鎖,除加鎖進程外其他進程沒有對已加鎖文件讀寫訪問權限,在任意時間內,一個文件的排他鎖只能被一個進程擁有。
LOCK_UN: 表示刪除該進程創建的鎖
LOCK_NB: 如果指定此參數,函數不能獲得文件鎖就立即返回,否則,函數會等待獲得文件鎖。LOCK_NB可以同LOCK_SH或LOCK_NB進行按位或(|)運算操作。 fcnt.flock(f,fcntl.LOCK_EX|fcntl.LOCK_NB)
LOCK_MAND:它主要是用於共享模式強制鎖,它可以與 LOCK_READ 或者 LOCK_WRITE 聯合起來使用,從而表示是否允許並發的讀操作或者並發的寫操作(盡管在 flock() 的手冊頁中沒有介紹LOCK_MAND,但是閱讀內核源代碼就會發現,這在內核中已經實現了)
# -*- coding:utf-8 -*-
'''
鎖類型(fcntl.flock函數的第二個參數)
LOCK_SH: 表示要創建一個共享鎖,在任意時間內,一個文件的共享鎖可以被多個進程擁有
LOCK_EX: 表示創建一個排他鎖,在任意時間內,一個文件的排他鎖只能被一個進程擁有
LOCK_UN: 表示刪除該進程創建的鎖
LOCK_MAND:它主要是用於共享模式強制鎖,它可以與 LOCK_READ 或者 LOCK_WRITE 聯合起來使用,從而
表示是否允許並發的讀操作或者並發的寫操作(盡管在 flock() 的手冊頁中沒有介紹
LOCK_MAND,但是閱讀內核源代碼就會發現,這在內核中已經實現了)
'''
import os
import sys
import time
import fcntl
import threading
import random
# 如下例子中,分別加鎖和不加鎖,結果
# 不加鎖時,多個線程間競爭文件寫權限,會出現覆蓋,導致寫內容不可預期(見test.log.withoutlock)
# 加鎖時,多個線程間會等待一個線程結束(因為設置的是阻塞鎖)后,第二個線程才開始寫,不會相互
# 覆蓋(見test.log.withlock)
def demo(name="null"):
fp = open("test.log", "a+")
cnt = 0
# 在3s內隨機等待一段時間,打亂加鎖順序
time.sleep(float(random.randint(0, 300)) / 300)
fcntl.flock(fp, fcntl.LOCK_EX)
print "call demo by %s" % name
# 在10s內進行寫入,為了避免寫入的內容過多,寫0.5s,停0.5s
for i in range(10):
# 寫0.5s
for i in range(100):
fp.write("write by %s, %d\n" % (name, cnt))
cnt += 1
time.sleep(0.005)
# 停0.5s
time.sleep(0.5)
fcntl.flock(fp, fcntl.LOCK_UN)
fp.close()
if __name__ == "__main__":
# 創建3個進程,並發寫入
for cnt in range(3):
name = "thread_%d" % cnt
thd = threading.Thread(target=demo, args=(name,))
thd.start()
未加鎖時,線程寫入異常