2019年9月16日の学習仕上げ
プロセス・ロック
質問:複数のプロセスが同じデータリソースを使用すると、データのセキュリティや秩序が混乱につながります。
票をつかむために優先順位
from multiprocessing import Process,Lock
import json,time,os
def search():
time.sleep(1) # 模拟网络io
with open('db.txt',mode='rt',encoding='utf-8') as f:
res = json.load(f)
print(f'还剩{res["count"]}')
def get():
with open('db.txt',mode='rt',encoding='utf-8') as f:
res = json.load(f)
# print(f'还剩{res["count"]}')
time.sleep(1) # 模拟网络io
if res['count'] > 0:
res['count'] -= 1
with open('db.txt',mode='wt',encoding='utf-8') as f:
json.dump(res,f)
print(f'进程{os.getpid()} 抢票成功')
time.sleep(1.5) # 模拟网络io
else:
print('票已经售空啦!!!!!!!!!!!')
def task(lock):
search()
# 锁住
lock.acquire()
get()
lock.release()
# 释放锁头
if __name__ == '__main__':
lock = Lock() # 写在主进程是为了让子进程拿到同一把锁.
for i in range(15):
p = Process(target=task,args=(lock,))
p.start()
# p.join()
# 进程锁 是把锁住的代码变成了串行
# join 是把所有的子进程变成了串行
# 为了保证数据的安全,串行牺牲掉效率.
ロックが同時にデータの同じ部分は、1つのタスクのみを修正することができることを確実にするために複数のプロセスを変更することができるとき、それは、連続変化します
キュー
IPC-プロセス間通信機構
パイプライン:パイプベースの共有メモリ空間
キュー:パイプ+ロックキュー
キュー
共有プロセスキューを作成、キューは、マルチプロセスセーフキューキューが複数のプロセス間でデータを渡すために使用することが可能です。
Queue([maxsize])
共有プロセスキューを作成します。
パラメータ:MAXSIZEはキューに許可されるエントリの最大数です。省略した場合、サイズ制限なし。
パイプを使用して、基礎となるキューの実装をロックします。
2.1.1メソッドの紹介
Queue([maxsize])
:共有プロセスのキューを作成します。MAXSIZEはキューに許可されるエントリの最大数です。省略した場合、サイズ制限なし。パイプを使用して、基礎となるキューの実装をロックします。また、スレッドは、基礎となるパイプに送信データキューをサポートするために実行する必要があります。
Qキューは、次の方法の例:
q.get( [ block [ ,timeout ] ] )
:プロジェクトqのリターン。qが空の場合、キューが使用可能なアイテムになるまで、このメソッドはブロックされます。ブロッキング動作を制御するためのブロック、デフォルトはTrueです。Falseに設定した場合は、例外Queue.Empty(キューモジュールで定義された)がスローされます。タイムアウトタイムアウトはブロッキングモードで使用するために、任意です。利用可能にする時間間隔内のプロジェクトへの変更がない場合、それはQueue.Empty例外につながります。
q.get_nowait()
:同じq.get(False)
方法。
q.put(item [, block [,timeout ] ] )
:キュー内のアイテムです。キューがいっぱいの場合はスペースが利用可能になるまで、このメソッドはブロックされます。挙動制御を遮断するブロックは、デフォルトはTrueです。Falseに設定した場合は、例外Queue.Empty(ライブラリモジュールのキューに定義された)がスローされます。タイムアウトはブロッキングモードでは、時間の利用可能なスペースのための待ち時間の長さを指定します。タイムアウト後Queue.Fullの例外を発生させました。
q.qsize()
:現在のプロジェクトのキュー正しい数を返します。この関数の結果は、理由を返す間、信頼性の高いものではなく、キューがアイテムを追加または削除することができ、プログラムの後の結果を使用しています。いくつかのシステムでは、この方法では、NotImplementedError例外につながる可能性があります。
q.empty()
:このメソッドは空の呼び出された場合にはQは、Trueを返します。他のプロセスやスレッドがキューに項目を追加している場合、その結果は信頼できません。それはリターンの間で、言うと結果を使用することで、キューが新しいプロジェクトに追加された可能性があります。
q.full()
:Qが原因スレッドの存在のために、フルである場合(参照結果は信頼できないことがあり、Trueを返すq.empty()
メソッド)。
2.1.2その他の方法(理解)
q.close()
:キューをオフにし、より多くのデータがキューを防止するために添加されます。あなたは、このメソッドを呼び出すと、バックグラウンドスレッドがキューに書き込まれていきますが、そのデータが書き込まれていないが、この方法が完了するとすぐに終了します。qがガベージコレクトされた場合、それは自動的にこのメソッドを呼び出します。閉じるキューは、データの任意のタイプまたはキュー内のユーザーの異常終了信号を生成しません。ユーザーがブロックされている場合、例えば、get()
操作、キューがプロデューサをもたらさない閉じるget()
方法がエラーを返します。
q.cancel_join_thread()
:バックグラウンドスレッドがプロセスから撤退しませんときに自動的に接続します。これは防ぐjoin_thread()
方法ブロックを。
q.join_thread()
:接続キューのバックグラウンドスレッド。このメソッドは呼び出すために使用されるq.close()
方法を、すべての待機中のキューアイテムが消費されています。デフォルトでは、この方法は、Qの原作者ではありませんすべてのプロセスによって呼び出されます。呼び出しq.cancel_join_thread()
、そのような行動を禁止することができる方法を
ケース
### 案例一
# q = Queue()
# q.put('鲁照山')
# q.put([1,2,4])
# q.put(2)
# print(q.get())
# print(q.get())
# print(q.get())
# # q.put(5)
# # q.put(5)
# print(q.get()) # 默认就会一直等着拿值
### 案例2
# q = Queue(4)
# q.put('鲁照山')
# q.put([1,2,4])
# q.put([1,2,4])
# q.put(2)
#
# q.put('乔碧萝') #队列满了的情况再放值,会阻塞
### 案例3 (从这往下都是了解)
# q = Queue(3)
# q.put('zhao',block=True,timeout=2) #
# q.put('zhao',block=True,timeout=2) #
# q.put('zhao',block=True,timeout=2) #
#
# q.put('zhao',block=True,timeout=5) # put里的 block=True 如果满了会等待,timeout最多等待n s,如果ns还是队列还是满的就报错了
### 案例4
# q = Queue()
# q.put('yyyy')
# q.get()
# q.get(block=True,timeout=5) # block=True 阻塞等待,timeout最多等5s, 剩下同上
### 案例5
# q = Queue(3)
# q.put('qwe')
# q.put('qwe')
# q.put('qwe')
#
# q.put('qwe',block=False) # 对于put来说block=False 如果队列满了就直接报错
# q = Queue(3)
# q.put('qwe')
# q.get()
#
#
# q.get(block=False)
# block = Flase 拿不到不阻塞,直接报错
### 案例6
q = Queue(1)
q.put('123')
# q.get()
q.put_nowait('666') # block = False
# q.get_nowait() # block = False
#
プロデューサーの消費者モデル
プロデューサー:生産データのタスクの
消費者:データ処理タスクの
生産者-キュー(ポット) - >消費者
生産者は彼らの最大の生産性に到達するために、生産を停止することはできません、消費者が支出を保つことができますまた、それらの最大消費効率に達した。
生産者-消費者モデルを大幅に個人消費効率の生産及び生産の効率を向上させます
補足:キューは、大容量のファイル転送、メッセージの一部による生産のパスには適していません。
並行プログラミングで生産者と消費者の使用パターンは、並行性の問題の大半を解決することができます。生産と消費のスレッドスレッドのバランスをとる能力を加工してデータ処理プログラムの速度を上げるために、全体的なパターン。
なぜ使用の生産者と消費者のパターン
スレッドの世界では、スレッドが本番データのプロデューサーである、消費者は、スレッド消費データです。迅速に処理プロデューサー、そして消費者の処理速度が非常に遅い場合、マルチスレッドの開発では、プロデューサは、生産データを継続するために、処理された消費者を待たなければなりません。消費者の能力がプロデューサーよりも大きい場合には、同じトークンによって、消費者は生産者を待たなければならないでしょう。その生産者と消費者のパターンの導入をこの問題を解決するには。
生産者 - 消費者モデルとは何ですか
生産者 - 消費者モデルは、容器の生産者と消費者によって解決される強い結合の問題です。生産者と消費者が直接相互に通信していない、とキューを遮断することによって通信する、消費者を待たずに本番データの処理が完了した後にプロデューサーので、直接スローのブロッキングキューは、消費者がデータへのプロデューサーを見つけることができませんが、キューをブロックから直接採取し、キューが処理能力の生産者と消費者のバランスをとる、ブロッキングバッファーに相当します。
from multiprocessing import Process,Queue,JoinableQueue
import time,random
def producer(q,name,food):
'''生产者'''
for i in range(3):
print(f'{name}生产了{food}{i}')
time.sleep(random.randint(1, 3))
res = f'{food}{i}'
q.put(res)
# q.put(None)
def consumer(q,name):
'''消费者'''
while True:
res = q.get()
# if res is None:break
time.sleep(random.randint(1,3))
print(f'{name}吃了{res}')
q.task_done() #
if __name__ == '__main__':
q = JoinableQueue()
p1 = Process(target=producer,args=(q,'rocky','包子'))
p2 = Process(target=producer,args=(q,'mac','韭菜'))
p3 = Process(target=producer,args=(q,'nick','蒜泥'))
c1 = Process(target=consumer,args=(q,'成哥'))
c2 = Process(target=consumer,args=(q,'浩南哥'))
p1.start()
p2.start()
p3.start()
c1.daemon = True
c2.daemon = True
c1.start()
c2.start()
p1.join()
p2.join()
p3.join() # 生产者生产完毕
# q.put(None)# 几个消费者put几次
# q.put(None)
q.join() # 分析
# 生产者生产完毕--这是主进程最后一行代码结束--q.join()消费者已经取干净了,没有存在的意义了.
#这是主进程最后一行代码结束,消费者已经取干净了,没有存在的意义了.守护进程的概念.
JoinableQueue
キューが接続できる共有プロセスを作成します。これは、キューのオブジェクトのようだが、キューは、ユーザは、プロジェクトが正常に処理されたプロジェクトのプロデューサーを通知することができます。通知プロセスが達成するために共有信号と条件変数を使用しています。
メソッドの紹介
同じ方法によりJoinableQueueキューオブジェクト以外Pの例は、本方法はさらに以下を含みます:
q.task_done()
この方法をq.get()はアイテムが処理された戻りユーザ信号を使用。このメソッドの呼び出しの数がキューから削除された項目の数より大きい場合、それはとValueErrorの例外が発生します。
q.join()
:キュー内のすべての項目が処理されるまで生産者は、このメソッドはブロックを使用します。ブロッキングは、各項目のためにキューイングしていきます)(メソッドq.task_doneを呼んでいます。
次の例では、永遠に実行するプロセスを作成して使用し、キュー上の処分プロジェクトする方法を示しています。プロデューサーは、キュー内に突出、およびそれらを処理するのを待ちます。
from multiprocessing import Process,Queue,JoinableQueue
q = JoinableQueue()
q.put('zhao') # 放队列里一个任务
q.put('qian')
print(q.get())
q.task_done() # 完成了一次任务
print(q.get())
q.task_done() # 完成了一次任务
q.join() #计数器不为0的时候 阻塞等待计数器为0后通过
# 想象成一个计数器 :put +1 task_done -1
知人のスレッド
早期の識別スレッド。
伝統的なオペレーティングシステムでは、各プロセスは、アドレス空間を持っていますが、コントロールのデフォルトのスレッドがある
工場では、各工場は家を持っており、各店舗では、デフォルトのラインを持っています。
OS ===>工場の
プロセス===>ワークショップの
スレッド===>パイプライン
CPU ===>パワー
スレッド:実行のCPU最小単位
プロセス:コレクション/リソースユニット
スレッドが実行=コードの実行
プロセス実行中のスレッド+リソースを=