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 #根據檔案名稱和內容,寫入檔案。成功返回1def 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-8from threading import Threadfrom time import sleepfrom 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)#定義線程T2def 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-8from threading import Threadfrom time import sleepfrom multiprocessing import Processfrom 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)#線程T1def 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中。
註:我們通過檔案鎖,解決了進程之間互斥操作同一個資源的問題。如果是同一個線程之間互斥操作同一個資源的問題,我們只需要定義個全域變數即可,我們沒有必要使用檔案鎖,因為檔案鎖需要訪問磁碟。