python3 進程鎖

  • 2020 年 1 月 13 日
  • 筆記

多進程搶佔資源 當多個進程使用同一份數據資源的時候,就會引發數據安全或順序混亂問題。

	import os  	import time  	import random  	from multiprocessing import Process,Lock    	def work(n):  	    print('%s: %s is runing' % (n,os.getpid()))  	    time.sleep(random.random())  	    print('%s: %s is down' % (n, os.getpid()))      	if __name__ == '__main__':  	    for i in range(3): # 利用for循環模擬多進程  	        p=Process(target=work,args=(i,))  	        p.start()    輸出結果:  0: 10974 is runing  1: 10975 is runing  2: 10976 is runing  1: 10975 is down  2: 10976 is down  0: 10974 is down

加鎖

# 由並發變成了串行,犧牲了運行效率,但避免了競爭  import os  import time  import random  from multiprocessing import Process,Lock    def work(lock,n):      lock.acquire()      print('%s: %s is runing' % (n,os.getpid()))      time.sleep(random.random())      print('%s: %s is down' % (n, os.getpid()))      lock.release()    if __name__ == '__main__':      lock = Lock()      for i in range(3):          p=Process(target=work,args=(lock,i))          p.start()    輸出結果:  0: 10986 is runing  0: 10986 is down  1: 10987 is runing  1: 10987 is down  2: 10988 is runing  2: 10988 is down

上面這種情況雖然使用加鎖的形式實現了順序的執行,但是程序又重新變成串行了,這樣確實會浪費了時間,卻保證了數據的安全。這個過程類似於數據庫的事務


例子:模擬搶票

沒有加鎖的情況,雖然實現了並發,但是數據不安全,本來只有一張票,但是還是會有多個人搶到,這顯然不符合現實

# 文件db的內容為:{"count":1}  # 注意一定要用雙引號,不然json無法識別  # 並發運行,效率高,但競爭寫同一文件,數據寫入錯亂    from multiprocessing import Process  import time,json,random    def search():      dic = json.load(open('db'))      print('33[43m剩餘票數%s33[0m' % dic['count'])    def get():      dic = json.load(open('db'))      time.sleep(0.1)   # 模擬讀數據延遲      if dic['count'] > 0:          dic['count'] -= 1          time.sleep(0.2)  # 模擬寫數據延遲          json.dump(dic,open('db','w'))          print('33[43m購票成功33[0m')    def task():      search()      get()    if __name__ == '__main__':      for i in range(100):    # 模擬並發100個客戶端搶票          p=Process(target=task)          p.start()

加鎖

# 文件db的內容為:{"count":5}  # 注意一定要用雙引號,不然json無法識別  # 並發運行,效率高,但競爭寫同一文件,數據寫入錯亂    from multiprocessing import Process,Lock  import time,json,random    def search():      dic=json.load(open('db'))      print('33[43m剩餘票數:%s33[0m' % dic['count'])    def get():      dic=json.load(open('db'))      time.sleep(random.random()) # 模擬讀數據的網絡延遲      if dic['count'] > 0:          dic['count'] -= 1          time.sleep(random.random()) # 模擬寫數據的網絡延遲          json.dump(dic,open('db','w'))          print('33[43m購票成功33[0m')        else:          print('33[43m余票不足33[0m')    def task(lock):      search()      lock.acquire()      get()      lock.release()    if __name__ == '__main__':      lock=Lock()      for i in range(100): # 模擬並發100個客戶端          p=Process(target=task,args=(lock,))          p.start()    輸出結果:  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  剩餘票數:5  購票成功  購票成功  購票成功  購票成功  購票成功  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足  余票不足    Process finished with exit code 0

因為只有5張票,因此加鎖後只會有5個人買到票,保證了數據的安全性。