目錄
- 一、進(jìn)程同步
- 二、為什么需要進(jìn)程同步
- 三、Python中實(shí)現(xiàn)進(jìn)程同步
-
四、多進(jìn)程模擬同時(shí)搶票
- 4.1 通過鎖控制進(jìn)程資源訪問
- 總結(jié)
盡管并發(fā)編程讓我們能更加充分的利用IO資源,但是也給我們帶來了新的問題: 當(dāng)多個(gè)進(jìn)程使用同一份數(shù)據(jù)資源的時(shí)候,就會(huì)引發(fā)數(shù)據(jù)安全或順序混亂問題。
一、進(jìn)程同步
多個(gè)進(jìn)程同時(shí)執(zhí)行,為了相互制約各進(jìn)程對(duì)資源的訪問,使得各個(gè)進(jìn)程的執(zhí)行相互同步。
在我的理解里,進(jìn)程同步也算是進(jìn)程間通訊(ipc)的一種手段。
二、為什么需要進(jìn)程同步
多進(jìn)程會(huì)引發(fā)搶占資源的問題,為了解決這個(gè)問題就需要各進(jìn)程之間相互同步,控制進(jìn)程對(duì)關(guān)鍵資源的訪問。
在C語言中實(shí)現(xiàn)進(jìn)程同步的方式有很多,比如:信號(hào)量,鎖機(jī)制等。
例子: 演示多進(jìn)程資源搶占問題
import os
import time
import random
from multiprocessing import Process
def work(n):
print('%s: %s is running' %(n,os.getpid()))
time.sleep(random.random())
print('%s:%s is done' %(n,os.getpid()))
if __name__ == '__main__':
for i in range(3):
p=Process(target=work,args=(i,))
p.start()
三、Python中實(shí)現(xiàn)進(jìn)程同步
-
首先
from multiprocessing import Lock -
在主進(jìn)程中,實(shí)例化得到鎖,
lock = Lock(),并傳給子進(jìn)程 -
在子進(jìn)程中通過上鎖和解鎖實(shí)現(xiàn)對(duì)多進(jìn)程對(duì)資源的控制。
lock.acquire()上鎖,lock.release()解鎖
演示:通過Python鎖機(jī)制控制資源的訪問
def work(lock,n):
print(f"等待開鎖 進(jìn)程{n}")
# 上鎖
lock.acquire() # 當(dāng)上鎖之后別的進(jìn)程無法訪問,會(huì)阻塞住
print(f'進(jìn)程{n} pid: %s is running' % ( os.getpid()))
time.sleep(random.random())
print(f'進(jìn)程{n} pid: %s is done' % (os.getpid()))
# 開鎖
lock.release()
if __name__ == '__main__':
lock=Lock() # 實(shí)例化得到鎖
for i in range(3):
p=Process(target=work,args=(lock,i))
p.start()
等待開鎖 進(jìn)程1
進(jìn)程1 pid: 8696 is running
等待開鎖 進(jìn)程0
等待開鎖 進(jìn)程2
進(jìn)程1 pid: 8696 is done
進(jìn)程0 pid: 14264 is running
進(jìn)程0 pid: 14264 is done
進(jìn)程2 pid: 22724 is running
進(jìn)程2 pid: 22724 is done
根據(jù)結(jié)果可以發(fā)現(xiàn),在上鎖之前的代碼。多進(jìn)程是并發(fā)訪問的,但上鎖之后,直到解鎖后才能有第二個(gè)人訪問。以此類推。 就好像上廁所排隊(duì)一樣,進(jìn)去一個(gè)人關(guān)上門鎖上,第二個(gè)人等著。
但是看完你會(huì)有個(gè)疑問,那被鎖上的代碼,每個(gè)進(jìn)程在訪問的時(shí)候不就是串行的依次在訪問嘛。
確實(shí),鎖機(jī)制 保證了數(shù)據(jù)的安全,但犧牲掉效率.
四、多進(jìn)程模擬同時(shí)搶票
# 文件db的內(nèi)容為:{"count":1}
# 注意一定要用雙引號(hào),不然json無法識(shí)別
# 并發(fā)運(yùn)行,效率高,但競爭寫同一文件,數(shù)據(jù)寫入錯(cuò)亂
from multiprocessing import Process,Lock
import time,json,random
def search():
dic=json.load(open('db'))
print('剩余票數(shù)%s' %dic['count'])
def get():
dic=json.load(open('db'))
time.sleep(0.1) # 模擬讀數(shù)據(jù)的網(wǎng)絡(luò)延遲
if dic['count'] >0:
dic['count']-=1
time.sleep(0.2) # 模擬寫數(shù)據(jù)的網(wǎng)絡(luò)延遲
json.dump(dic,open('db','w'))
print('購票成功')
def task():
search()
get()
if __name__ == '__main__':
for i in range(100): # 模擬并發(fā)100個(gè)客戶端搶票
p=Process(target=task)
p.start()
上述代碼,你會(huì)發(fā)現(xiàn)多個(gè)進(jìn)程在同時(shí)搶票,相互搶占文件資源,每個(gè)進(jìn)程都把文件讀入到內(nèi)存中進(jìn)行搶票。實(shí)際上,資源只能被一個(gè)人占有,這就會(huì)引發(fā)問題
4.1 通過鎖控制進(jìn)程資源訪問
def search():
time.sleep(1)
with open("db","w",encoding="utf8") as f:
data = json.load(f)
print(f'還剩{data["count"]}')
def get():
with open('db','rt',encoding='utf-8') as f:
res = json.load(f)
time.sleep(1) # 模擬網(wǎng)絡(luò)io
if res['count'] > 0:
res['count'] -= 1
with open('db', 'w', encoding='utf-8') as f:
json.dump(res, f)
print(f'進(jìn)程{os.getpid()} 搶票成功')
time.sleep(1.5) # 模擬網(wǎng)絡(luò)io
else:
print('票已經(jīng)售空啦!!!!!!!!!!!')
def task(lock):
print(f"進(jìn)程:{os.getpid()} 正在搶票中。。。")
# 上鎖 每個(gè)進(jìn)程都會(huì)訪問一遍,所以加鎖就等于上鎖到解鎖這段代碼是串行的
lock.acquire() # 當(dāng)上鎖之后別的進(jìn)程無法訪問,會(huì)阻塞住
get()
# 開鎖
lock.release()
if __name__ == '__main__':
# 創(chuàng)建鎖
lock = Lock()
pro_list = []
# 創(chuàng)建進(jìn)程
for i in range(10):
p = Process(target=task, args=(lock,))
p.start()
pro_list.append(p)
# 回收進(jìn)程
for i in range(10):
pro_list[i].join()
總結(jié)
進(jìn)程同步理論上應(yīng)該是進(jìn)程間通訊中的一部分,是一個(gè)大話題,每個(gè)語言也都有實(shí)現(xiàn)進(jìn)程同步的需求。需要將各個(gè)進(jìn)程對(duì)資源的訪問加以限制。在各個(gè)語言中也都有限制。這里目前只介紹了這一種進(jìn)程同步的方法。
鎖機(jī)制 是把鎖住的代碼變成了串行,保證了數(shù)據(jù)的安全,但犧牲掉效率.
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

