1. 程式人生 > >並發編程(互斥鎖)

並發編程(互斥鎖)

sin ces 方案 鎖定 沒有 是把 process 要去 復雜

一 互斥鎖

進程之間數據不共享,但是共享同一套文件系統,所以訪問同一個文件,或同一個打印終端,是沒有問題的,而共享帶來的是競爭,競爭帶來的結果就是錯亂,如下

就是為了,對可以並發操作的時候可以並發操作,對不可並發的時候進行鎖, 保證數據安全性

進程之間數據不共享,但是共享同一套文件系統,所以訪問同一個文件,或同一個打印終端,是沒有問題的,而共享帶來的是競爭,競爭帶來的結果就是錯亂,如下

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#並發運行,效率高,但競爭同一打印終端,帶來了打印錯亂
from multiprocessing import Process
import os,time def work(): print(%s is running %os.getpid()) time.sleep(2) print(%s is done %os.getpid()) if __name__ == __main__: for i in range(3): p=Process(target=work) p.start() #輸出 7908 is running 9432 is running 1760 is running 7908 is done 9432 is done 1760 is
done

如何控制,就是加鎖處理。而互斥鎖的意思就是互相排斥,如果把多個進程比喻為多個人,互斥鎖的工作原理就是多個人都要去爭搶同一個資源:衛生間,一個人搶到衛生間後上一把鎖,其他人都要等著,等到這個完成任務後釋放鎖,其他人才有可能有一個搶到......所以互斥鎖的原理,就是把並發改成穿行,降低了效率,但保證了數據安全不錯亂

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#並發運行,效率高,但競爭同一打印終端,帶來了打印錯亂
from multiprocessing import Process,Lock #
import os,time
#由並發變成了串行,犧牲了運行效率,但避免了競爭 def work(lock): lock.acquire() #加鎖 print(%s is running %os.getpid()) time.sleep(2) print(%s is done %os.getpid()) lock.release() #釋放鎖 if __name__ == __main__: lock=Lock() for i in range(3): p=Process(target=work,args=(lock,)) p.start() #輸出 5604 is running 5604 is done 1068 is running 1068 is done 14012 is running 14012 is done

在這裏 可以看出跟join 差不多,都是將並行變為串行, 但是 互斥鎖可以在需要的地方鎖定,解鎖,而join 只能等一個進程運行結束,才會執行下一個

總結

加鎖可以保證多個進程修改同一塊數據時,同一時間只能有一個任務可以進行修改,即串行地修改,沒錯,速度是慢了,但犧牲了速度卻保證了數據安全。

雖然可以用文件共享數據實現進程間通信,但問題是:

1、效率低(共享數據基於文件,而文件是硬盤上的數據)

2、需要自己加鎖處理

因此我們最好找尋一種解決方案能夠兼顧:

1、效率高(多個進程共享一塊內存的數據)

2、幫我們處理好鎖問題。

這就是mutiprocessing模塊為我們提供的基於消息的IPC通信機制:隊列和管道。

隊列和管道都是將數據存放於內存中,而隊列又是基於(管道+鎖)實現的,可以讓我們從復雜的鎖問題中解脫出來,因而隊列才是進程間通信的最佳選擇。

我們應該盡量避免使用共享數據,盡可能使用消息傳遞和隊列,避免處理復雜的同步和鎖問題,而且在進程數目增多時,往往可以獲得更好的可獲展性。

並發編程(互斥鎖)