1.文件鎖
問題:進程P1中有一個線程T1,T1執行的函數為f1;進程P2中有一個線程T2,T2執行的函數為f2。
當f1和f2都需要對同一個資源進行操作時,比如同時對文件file1進行操作。為了線程安全,則當f1在操作(讀或寫文件file1)時,不允許f2操作(讀或寫文件file1)。反之,當f2在操作file1時,不允許f1操作file1。即f1和f2不能同時操作file1。
解決方法:
可以采用文件鎖(這裡文件鎖的意思為將對資源file1的訪問狀態保存在文件fs.txt裡,即通過文件fs.txt來加鎖)的方式,對文件file1輪流交替的操作:即f1操作完file1之後,f2開始操作file1;當f2操作完file1之後,f1開始操作file1,這樣交替下去。
可以設置4種狀態:00、11、22、33。將這4種狀態保存在文件‘fs.txt’裡,因為這樣進程P1和P2都可以操作文件fs.txt(解決了進程間相互通信的問題)。4種狀態分別表示如下:
00:表示f1可以操作資源file1了,同時也表示f2操作完畢file1;
11:表示f1正在操作資源file1;
22:表示f1操作完畢file1,同時也表示f2可以操作file1了;
33:表示f2正在操作file1。
訪問流程圖如下所示:
我們可以看到,函數f1的狀態順序為'00' ->'11' -> '22';函數f2的狀態順序為'22' -> '33' -> '00'。
形成了如下的環形交替訪問:
2.Python中多進程的使用
下面將python中多進程的使用和文件鎖進行結合,給出一個簡單的demo。
公共函數(讀文件、寫文件)定義在文件GlobalFunc.py中:
- # encoding: utf-8
-
- #根據文件名,讀取文件內容
- def read_file(filename):
- all_the_text = ''
- fo = open(filename)
- try:
- all_the_text = fo.read()
- finally:
- fo.close()
- return all_the_text
-
-
- #根據文件名和內容,寫入文件。成功返回1
- def write_file(filename, filecontent):
- status = 0
- try:
- fo = open(filename, 'wb+')
- fo.write(filecontent)
- status = 1
- finally:
- fo.close()
- return status
進程P2的文件Process2.py定義如下:
- # encoding: utf-8
- from threading import Thread
- from time import sleep
- from GlobalFunc import read_file,write_file
-
- #定義線程T2的執行函數
- def f2():
- fs = read_file('fs.txt')
- print '\nP2 want to visit,now fs:',fs
- if '22' == fs: #f1操作完file1,f2可以開始操作了
- write_file('fs.txt','33') #表明f2正在操作file1
-
- print 'P2 is visiting file1...'
-
- write_file('fs.txt','00')
- sleep(10)
- else:
- sleep(1)
-
- #定義線程T2
- def T2():
- while True:
- f2()
-
- def main():
- print '\nlauch process:P2...'
- #啟動線程T2
- Thread(target = T2,args=()).start()
- while True:
- sleep(3)
-
- if __name__ == '__main__':
- main()
進程P1的文件Process.py定義如下:
- # encoding: utf-8
- from threading import Thread
- from time import sleep
- from multiprocessing import Process
- from GlobalFunc import read_file,write_file
-
- #線程T1的執行函數
- def f1():
- fs = read_file('fs.txt')
- print '\nP1 want to visit,now fs:',fs
- assert('00' == fs)
- if '00' == fs: #f2操作完file1,f1可以開始操作了
- write_file('fs.txt','11') #表明f1正在操作file1
-
- print 'P1 is visiting file1...'
-
- write_file('fs.txt','22')
- sleep(10)
- else:
- sleep(1)
-
- #線程T1
- def T1():
- while True:
- f1()
-
- if __name__ == '__main__':
- print 'lauch process:P1...'
- #初始化'fs.txt'
- write_file('fs.txt','00')
-
- #進程P2的定義
- from Process2 import main as P2_main
- P2 = Process(target = P2_main, args=())
- P2.start()
-
- #啟動線程T1
- Thread(target = T1,args=()).start()
-
- while True:
- sleep(3)
進程P2單獨定義成一個文件'Process2.py'。通過進程P1來調用啟動進程P2,進程P1中有一個線程T1,進程P2中有一個線程T2,T1和T2都對文件file1進行操作。我們通過'fs.txt'這個文件設置文件鎖,將T1和T2的當前操作狀態保存在fs.txt中。
注:我們通過文件鎖,解決了進程之間互斥操作同一個資源的問題。如果是同一個線程之間互斥操作同一個資源的問題,我們只需要定義個全局變量即可,我們沒有必要使用文件鎖,因為文件鎖需要訪問磁盤。