python之多執行緒多程序併發通訊
阿新 • • 發佈:2018-12-15
1.獨立的程序記憶體空間與共享的伺服器程序空間
程序之間是:互不干擾的獨立記憶體空間
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/10/16 7:59 # @Author : DoubleChina # @Site : # @File : ConcurrentTest.py # @Software: PyCharm # 併發通訊 from multiprocessing import Process a = 1 def func(): global a a = 2 p = Process(target=func()) p.start() p.join() #輸出的是1,並不是2,兩個程序之間沒有共享記憶體 print(a)
解決了記憶體共享的問題
from multiprocessing import Process, Manager
#啟動伺服器程序
mgr = Manager()
#list、dict、queue
d = mgr.dict()
# d = dict()
print(type(d))
def func(d):
d['a'] = 'a'
p = Process(target=func, args=(d,))
p.start()
p.join()
#{'a': 'a'} ,伺服器程序間共享了資料
print(d)
一般常用的空間型別是:
- mgr.list()
- mgr.dict()
- mgr.Queue()
##2.執行緒間共享的全域性變數與同步鎖的基本概念 因為執行緒屬於同一個程序,因此它們之間共享記憶體區域。因此全域性變數是公共的。
import threading
a = 1
def func():
global a
a = 2
t = threading.Thread(target=func)
t.start()
t.join()
#輸出2,共享了全域性變數
print(a)
多執行緒同時訪問一個變數,資源競爭導致資料異常
# 2個執行緒分別執行1萬次a+1 from threading import Thread a = 0 n = 100000 def incr(n): global a for i in range(n): a = a + 1 def dncr(n): global a for i in range(n): a = a - 1 t1 = Thread(target=incr, args=(n,)) t2 = Thread(target=dncr, args=(n,)) t1.start() t2.start() t1.join() t2.join() #輸出不一定是0 print(a)
加鎖解決資源競爭問題
from threading import Thread, Lock
a = 0
n = 100000
lock = Lock() # 建立鎖
def incr(n):
global a
for i in range(n):
lock.acquire() # 獲取鎖
a = a + 1
lock.release() # 釋放鎖
def dncr(n):
global a
for i in range(n):
lock.acquire() # 獲取鎖,如果t1執行緒獲取了鎖,就會進入阻塞
a = a - 1
lock.release() # 釋放鎖
t1 = Thread(target=incr, args=(n,))
t2 = Thread(target=dncr, args=(n,))
t1.start()
t2.start()
t1.join()
t2.join()
#輸出是0
print(a)
##3.執行緒與程序安全的佇列 佇列:一個入口,一個出口先入先出(FIFO)
執行緒佇列
# 執行緒佇列
import queue
q = queue.Queue(2)
q.put(1)
q.put(2)
# q.put(3, block=False) # 阻塞
#獲取佇列
print(q.get())
# 測試佇列是否滿了
print(q.full())
# 判斷佇列是否是空的
print(q.empty())
# 佇列大小
print(q.qsize())
# 等待佇列完成
print(q.join())
# 任務結束:
print(q.task_done())
程序佇列
# 程序佇列
from multiprocessing import Queue, Process
q = Queue()
q.put(1)
def func(q):
# 佇列有資料,共享資源
print(q.get())
p = Process(target=func, args=(q,))
p.start()
p.join()
# print(q.get())
如果只是一個執行緒/程序在使用,那麼它並不算公共資源。 但是一旦多個執行緒/程序在同時使用,那麼它就是一個公共資源。 如果被當作公共資源使用,那麼按理說是必須要加鎖的。但是,執行緒安全或程序安全的佇列中已經幫我們實現了鎖。因此我們不需要再自己使用鎖來同步。
4.消費者與生產者模式
生產者與消費者模型:其實是把一個需要程序通訊的問題分開考慮 生產者,只需要往佇列裡面丟東西(生產者不需要關心消費者) 消費者,只需要從佇列裡面拿東西(消費者也不需要關心生產者)
import threading
import random
import queue
import time
class Producer(threading.Thread):
def __init__(self, queue):
super().__init__()
self.queue = queue
def run(self):
for i in range(10):
r = random.randint(0, 9)
if not self.queue.full():
self.queue.put(r)
print('佇列裡面添加了一個數據{}'.format(r))
time.sleep(2)
else:
print('滿了')
class Consumer(threading.Thread):
def __init__(self, queue):
super().__init__()
self.queue = queue
def run(self):
while True:
# if not self.queue.empty(): # 判斷是否為空
data = self.queue.get()
time.sleep(2)
print('從佇列裡面獲取資料{}'.format(data))
self.queue.task_done() # 通知佇列
if __name__ == '__main__':
q = queue.Queue()
p1 = Producer(q)
c1 = Consumer(q)
p1.start()
c1.start()
p1.join()
c1.join()
q.join()
程序&執行緒使用佇列
# 普通的佇列,不能用在多程序通訊
import queue
#在程序中使用Manager() 、 Queue()
from multiprocessing import Queue,Manager