併發程式設計 之程序相關
阿新 • • 發佈:2018-12-29
# 1.守護程序 1個程序b 他的守護程序a 在被守護程序b死亡的時候a已死亡
# 應用場景 在執行的qq過程中,開啟了一個程序 用於下載檔案 然而檔案還沒有下完qq就退出了 下載任務也應該跟隨qq的退出而結束
# import time
# from multiprocessing import Process,Lock
#
#
#
# def task():
# print('妃子的一生')
# time.sleep(5)
# print('妃子涼涼了')
#
#
# if __name__ == '__main__':
# fz = Process(target=task)
# fz.daemon = True
# fz.start()
# print('皇帝登基了')
# time.sleep(2)
# print('當了10年皇帝')
# print('皇帝駕崩了')
# 2.互斥鎖
# 當多個程序共享資料時候時,可能會造成資料錯亂
# 1.使用join ,來讓這些程序序列 但是這將造成無法併發,程序執行任務的順序就固定了.
# 2.使用同一把鎖 將需要共享的資料加鎖 其他程序在訪問資料的時候 那就必須等待當前程序使用完畢
# 鎖的本質 就是一個bool型別的資料,在執行程式碼前會先判斷這個值
#必須保證鎖是同一把
#鎖的實現原理虛擬碼:
#
# l=False
#
# def task4(lock):
# global l
# if l == False:
# l=True
# print('my name is 2')
# time.sleep(random.randint(1,2))
# print('my age is 19')
# l=False
#
#
#
#
#
#
#
#
# import random
# import time
#
#
# def task1(lock):
# lock.acquire() # 是一個阻塞函式 會等到別的程序釋放鎖時才能繼續執行
# print('my name is 1')
# time.sleep(random.randint(1,2))
# print('my age is 18')
# lock.release()
#
# def task2(lock):
# lock.acquire()
# print('my name is 2')
# time.sleep(random.randint(1,2))
# print('my age is 19')
# lock.release()
#
# def task3(lock):
# lock.acquire()
# print('my name is 3')
# time.sleep(random.randint(1,2))
# print('my age is 20')
# lock.release()
#
# if __name__ == '__main__':
# lock=Lock()
# p1 = Process(target=task1,args=(lock,))
# p1.start()
# p2 = Process(target=task2,args=(lock,))
# p2.start()
# p3 = Process(target=task3,args=(lock,))
# p3.start()
#多個任務在共享一個數據 序列效率低 但是不會出現問題 併發效率高但是資料可能錯亂
#模擬搶票
# import json,time,random
# from multiprocessing import Process,Lock
# def check_ticket(usr):
# with open("ticket.json",'r',encoding='utf-8') as f:
# dic =json.load(f)
# print('%s檢視剩餘票數%s'%(usr,dic['count']))
#
# def buy_ticket(usr):
# with open("ticket.json",'r',encoding='utf-8') as f:
# dic =json.load(f)
# if dic['count'] > 0:
# time.sleep(random.randint(1,2))
# dic['count']-=1
# with open('ticket.json','w',encoding='utf-8')as f2:
# json.dump(dic,f2)
# print('%s購買成功!'%usr)
#
#
# def task(usr,lock):
# check_ticket(usr)
# lock.acquire()
# buy_ticket(usr)
# lock.release()
# if __name__ == '__main__':
# lock = Lock()
#
#
# for i in range(5):
# p=Process(target=task,args=('使用者%s'%i,lock))
# p.start() #首先全部併發檢視票,然後買票的時候序列
#join 和鎖的區別
# 1.join中的順序是固定的 不公平
# 2.join是完全序列 而鎖可以讓部門程式碼序列,其他程式碼併發
# #Lock 和 Rlock的區別
# from multiprocessing import RLock
# # 1.在lock下 如果在執行程式碼前添加了2次lock.acquire() ,程式碼將無法執行
# lock = Lock()
# lock.acquire()
# lock.acquire()
# print('哈哈')
# lock.release()
# # 2.在Rlock模式下 如果在執行程式碼前新增無數次lock.acquire(),程式碼都可以執行. 表示重入鎖 可以多次執行acquire
#
# lock = RLock()
# lock.acquire()
# lock.acquire()
# print('哈哈')
# lock.release()
#
#
#
#
#
# import time
#
# def task5(i):
# lock.acquire()
# lock.acquire()
# print(i)
# time.sleep(3)
# lock.release()
#
# if __name__ == '__main__':
# lock = RLock
# p1 = Process(target=task5,args=(1,lock))
# p1.start()
# p2 = Process(target=task5,args=(2,lock))
# p2.start()
# 當RLock存在2個程序進行競爭的時候 :
# 當只有一次acquire的時候也可以起到鎖的作用;在程式碼中即為先列印了1之後過3秒再列印2
# 如果增加了一次acquire的執行次數而不新增release的次數,將會阻塞在第二個acquire, 即只打印出1,2不列印
# ipc程序間的通訊
# 三種方式:
# 1. 使用共享檔案,過個程序同時讀寫一個檔案
# i/o速度慢,傳輸大小不受限制
# 2.管道 是基於記憶體的速度快 但是是單向的 用起來麻煩
# 3.申請共享記憶體空間,多個程序可以共享這個記憶體區域,速度快 但是資料量不能太大
from multiprocessing import Manager,Process
def work(d):
d['count']-=1
if __name__ == '__main__':
# 開啟了一個Manager共享記憶體
with Manager() as m:
dic = m.dict({'count':2}) #在這個空間中儲存了一個字典
p_l = []
for i in range(2):
p=Process(target=work,args=(dic,))
p_l.append(p)
p.start() #就緒狀態
for p in p_l:
p.join()
print(dic)
#相當於給子程序進行了序列
#佇列: 不止用於程序之間的通訊 先進先出
from multiprocessing import Queue
q = Queue(1) #建立1個佇列 最多可以存一個數據
q.put('a') #將a裝入到佇列中
q.put('b',False) #程式阻塞 put預設阻塞 當容器裡面裝滿繼續裝就會阻塞住
# 2.put中如果第二個引數設定為False 表示不會阻塞無論容器是否塞滿,都會強行塞,如果滿了就拋異常
print(q.get()) #取出一個數據a
print(q.get()) #沒有新增資料第二次取無資料就阻塞 預設阻塞
# 如果get中引數設為False 也是非阻塞,當取完了還要去取就報錯
# 其中還有個引數timeout= 設定為3的時候表示 當阻塞狀態下3秒還沒有拿到資料會報錯