Python隊(duì)列、進(jìn)程間通信、線程案例
進(jìn)程互斥鎖
多進(jìn)程同時(shí)搶購(gòu)余票
# 并發(fā)運(yùn)行,效率高,但競(jìng)爭(zhēng)寫(xiě)同一文件,數(shù)據(jù)寫(xiě)入錯(cuò)亂
# data.json文件內(nèi)容為 {"ticket_num": 1}
import json
import time
from multiprocessing import Process
def search(user):
with open('data.json', 'r', encoding='utf-8') as f:
dic = json.load(f)
print(f'用戶(hù){user}查看余票,還剩{dic.get("ticket_num")}...')
def buy(user):
with open('data.json', 'r', encoding='utf-8') as f:
dic = json.load(f)
time.sleep(0.1)
if dic['ticket_num'] > 0:
dic['ticket_num'] -= 1
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(dic, f)
print(f'用戶(hù){user}搶票成功!')
else:
print(f'用戶(hù){user}搶票失敗')
def run(user):
search(user)
buy(user)
if __name__ == '__main__':
for i in range(10): # 模擬10個(gè)用戶(hù)搶票
p = Process(target=run, args=(f'用戶(hù){i}', ))
p.start()
使用鎖來(lái)保證數(shù)據(jù)安全
# data.json文件內(nèi)容為 {"ticket_num": 1}
import json
import time
from multiprocessing import Process, Lock
def search(user):
with open('data.json', 'r', encoding='utf-8') as f:
dic = json.load(f)
print(f'用戶(hù){user}查看余票,還剩{dic.get("ticket_num")}...')
def buy(user):
with open('data.json', 'r', encoding='utf-8') as f:
dic = json.load(f)
time.sleep(0.2)
if dic['ticket_num'] > 0:
dic['ticket_num'] -= 1
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(dic, f)
print(f'用戶(hù){user}搶票成功!')
else:
print(f'用戶(hù){user}搶票失敗')
def run(user, mutex):
search(user)
mutex.acquire() # 加鎖
buy(user)
mutex.release() # 釋放鎖
if __name__ == '__main__':
# 調(diào)用Lock()類(lèi)得到一個(gè)鎖對(duì)象
mutex = Lock()
for i in range(10): # 模擬10個(gè)用戶(hù)搶票
p = Process(target=run, args=(f'用戶(hù){i}', mutex))
p.start()
進(jìn)程互斥鎖:
讓并發(fā)變成串行,犧牲了執(zhí)行效率,保證了數(shù)據(jù)安全
在程序并發(fā)時(shí),需要修改數(shù)據(jù)使用
隊(duì)列
隊(duì)列遵循的是先進(jìn)先出
隊(duì)列:相當(dāng)于內(nèi)存中一個(gè)隊(duì)列空間,可以存放多個(gè)數(shù)據(jù),但數(shù)據(jù)的順序是由先進(jìn)去的排在前面。
q.put() 添加數(shù)據(jù)
q.get() 取數(shù)據(jù),遵循隊(duì)列先進(jìn)先出
q.get_nowait() 獲取隊(duì)列數(shù)據(jù), 隊(duì)列中沒(méi)有就會(huì)報(bào)錯(cuò)
q.put_nowait 添加數(shù)據(jù),若隊(duì)列滿(mǎn)了也會(huì)報(bào)錯(cuò)
q.full() 查看隊(duì)列是否滿(mǎn)了
q.empty() 查看隊(duì)列是否為空
from multiprocessing import Queue
# 調(diào)用隊(duì)列類(lèi),實(shí)例化隊(duì)列對(duì)象
q = Queue(5) # 隊(duì)列中存放5個(gè)數(shù)據(jù)
# put添加數(shù)據(jù),若隊(duì)列里的數(shù)據(jù)滿(mǎn)了就會(huì)卡住
q.put(1)
print('進(jìn)入數(shù)據(jù)1')
q.put(2)
print('進(jìn)入數(shù)據(jù)2')
q.put(3)
print('進(jìn)入數(shù)據(jù)3')
q.put(4)
print('進(jìn)入數(shù)據(jù)4')
q.put(5)
print('進(jìn)入數(shù)據(jù)5')
# 查看隊(duì)列是否滿(mǎn)了
print(q.full())
# 添加數(shù)據(jù), 若隊(duì)列滿(mǎn)了也會(huì)報(bào)錯(cuò)
q.put_nowait(6)
# q.get() 獲取的數(shù)據(jù)遵循先進(jìn)先出
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
# print(q.get())
print(q.get_nowait()) # 獲取隊(duì)列數(shù)據(jù), 隊(duì)列中沒(méi)有就會(huì)報(bào)錯(cuò)
# 判斷隊(duì)列是否為空
print(q.empty())
q.put(6)
print('進(jìn)入數(shù)據(jù)6')
進(jìn)程間通信
IPC(Inter-Process Communication)
進(jìn)程間數(shù)據(jù)是相互隔離的,若想實(shí)現(xiàn)進(jìn)程間通信,可以利用隊(duì)列
from multiprocessing import Process, Queue
def task1(q):
data = 'hello 你好'
q.put(data)
print('進(jìn)程1添加數(shù)據(jù)到隊(duì)列')
def task2(q):
print(q.get())
print('進(jìn)程2從隊(duì)列中獲取數(shù)據(jù)')
if __name__ == '__main__':
q = Queue()
p1 = Process(target=task1, args=(q, ))
p2 = Process(target=task2, args=(q, ))
p1.start()
p2.start()
print('主進(jìn)程')
生產(chǎn)者與消費(fèi)者
在程序中,通過(guò)隊(duì)列生產(chǎn)者把數(shù)據(jù)添加到隊(duì)列中,消費(fèi)者從隊(duì)列中獲取數(shù)據(jù)
from multiprocessing import Process, Queue
import time
# 生產(chǎn)者
def producer(name, food, q):
for i in range(10):
data = food, i
msg = f'用戶(hù){name}開(kāi)始制作{data}'
print(msg)
q.put(data)
time.sleep(0.1)
# 消費(fèi)者
def consumer(name, q):
while True:
data = q.get()
if not data:
break
print(f'用戶(hù){name}開(kāi)始吃{data}')
if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=('neo', '煎餅', q))
p2 = Process(target=producer, args=('wick', '肉包', q))
c1 = Process(target=consumer, args=('cwz', q))
c2 = Process(target=consumer, args=('woods', q))
p1.start()
p2.start()
c1.daemon = True
c2.daemon = True
c1.start()
c2.start()
print('主')
線程
線程的概念
進(jìn)程與線程都是虛擬單位
進(jìn)程:資源單位
線程:執(zhí)行單位
開(kāi)啟一個(gè)進(jìn)程,一定會(huì)有一個(gè)線程,線程才是真正執(zhí)行者
開(kāi)啟進(jìn)程:
- 開(kāi)辟一個(gè)名稱(chēng)空間,每開(kāi)啟一個(gè)進(jìn)程都會(huì)占用一份內(nèi)存資源
- 會(huì)自帶一個(gè)線程
開(kāi)啟線程:
- 一個(gè)進(jìn)程可以開(kāi)啟多個(gè)線程
- 線程的開(kāi)銷(xiāo)遠(yuǎn)小于進(jìn)程
注意:線程不能實(shí)現(xiàn)并行,線程只能實(shí)現(xiàn)并發(fā),進(jìn)程可以實(shí)現(xiàn)并行
線程的兩種創(chuàng)建方式
from threading import Thread
import time
# 創(chuàng)建線程方式1
def task():
print('線程開(kāi)啟')
time.sleep(1)
print('線程結(jié)束')
if __name__ == '__main__':
t = Thread(target=task)
t.start()
# 創(chuàng)建線程方式2
class MyThread(Thread):
def run(self):
print('線程開(kāi)啟...')
time.sleep(1)
print('線程結(jié)束...')
if __name__ == '__main__':
t = MyThread()
t.start()
線程對(duì)象的方法
from threading import Thread
from threading import current_thread
import time
def task():
print(f'線程開(kāi)啟{current_thread().name}')
time.sleep(1)
print(f'線程結(jié)束{current_thread().name}')
if __name__ == '__main__':
t = Thread(target=task)
print(t.isAlive())
# t.daemon = True
t.start()
print(t.isAlive())
線程互斥鎖
線程之間數(shù)據(jù)是共享的
from threading import Thread
from threading import Lock
import time
mutex = Lock()
n = 100
def task(i):
print(f'線程{i}啟動(dòng)')
global n
mutex.acquire()
temp = n
time.sleep(0.1)
n = temp - 1
print(n)
mutex.release()
if __name__ == '__main__':
t_l = []
for i in range(100):
t = Thread(target=task, args=(i, ))
t_l.append(t)
t.start()
for t in t_l:
t.join()
print(n)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python實(shí)現(xiàn)csv格式文件轉(zhuǎn)為asc格式文件的方法
下面小編就為大家分享一篇python實(shí)現(xiàn)csv格式文件轉(zhuǎn)為asc格式文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
使用Python畫(huà)了一棵圣誕樹(shù)的實(shí)例代碼
這篇文章主要介紹了使用Python畫(huà)了一棵圣誕樹(shù)的實(shí)例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
python 申請(qǐng)內(nèi)存空間,用于創(chuàng)建多維數(shù)組的實(shí)例
今天小編就為大家分享一篇python 申請(qǐng)內(nèi)存空間,用于創(chuàng)建多維數(shù)組的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12
selenium鼠標(biāo)操作實(shí)戰(zhàn)案例詳解
在實(shí)際場(chǎng)景中,會(huì)有單擊、長(zhǎng)時(shí)間單擊、雙擊、右鍵、拖拽等鼠標(biāo)操作,selenium提供了名為ActionChains的類(lèi)來(lái)處理這些操作,下面這篇文章主要給大家介紹了關(guān)于selenium鼠標(biāo)操作實(shí)戰(zhàn)案例的相關(guān)資料,需要的朋友可以參考下2023-05-05
Python爬蟲(chóng)常用庫(kù)的安裝及其環(huán)境配置
今天小編就為大家分享一篇關(guān)于python爬蟲(chóng)常用庫(kù)的安裝及其環(huán)境配置的文章,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-09-09
python OpenCV的imread不能讀取中文路徑問(wèn)題及解決
這篇文章主要介紹了python OpenCV的imread不能讀取中文路徑問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
python調(diào)用opencv實(shí)現(xiàn)貓臉檢測(cè)功能
這篇文章主要介紹了python調(diào)用opencv實(shí)現(xiàn)貓臉檢測(cè)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
Python處理JSON時(shí)的值報(bào)錯(cuò)及編碼報(bào)錯(cuò)的兩則解決實(shí)錄
這篇文章主要介紹了Python處理JSON時(shí)的值報(bào)錯(cuò)及編碼報(bào)錯(cuò)的兩則解決實(shí)錄,在這里還是想建議一下使用Python 3.x版本,Python 3默認(rèn)的Unicode編碼能在實(shí)際使用中為我們省去不少問(wèn)題,需要的朋友可以參考下2016-06-06
Python設(shè)計(jì)模式之模板方法模式實(shí)例詳解
這篇文章主要介紹了Python設(shè)計(jì)模式之模板方法模式,結(jié)合實(shí)例形式較為詳細(xì)的分析了模板方法模式的概念、原理及Python定義、使用模板方法模式相關(guān)操作技巧,需要的朋友可以參考下2019-01-01

