数分間のpythonマルチスレッドの詳細な解釈

マルチスレッド

マルチスレッディングとは、実際にはナルトアバターに相当します。これは、同時に1つのことを実行できる複数のミラーアバターがある5次元空間に相当します。また、入浴中にコーヒーを飲むことにも相当します。前の言葉についてブログを書きました。
数分pythonマルチスレッドを取得できますが、タイトルを見ると、記述が包括的ではなく、追加することがたくさんあることがわかります。したがって、ここで完全な要約を作成すると、一方では自分自身と他の人にとって便利です。

マルチスレッドを使用する(スレッド)

pythonでマルチスレッドを使用するには、モジュールスレッドを使用できます。
XiaomingとXiaohongの実行の前の例は、まだ比較的抽象的で理解が難しいため、ここでは使用されていません。
最初にスレッド化
ステップをインポートします
。1スレッドの作成ming = threading.Thread(target = target function、args = [value])
2スレッドの宣言ming.setDaemon(True)
3スレッドの実行ming.start()
4スレッドの待機ming.join()
ここでは、シャオホンとシャオミンが急行を希望していると仮定します。
宅配便を利用する方法は2つあります。1つは1人で、2つは2人で一緒に利用します。
明らかに、2人でそれをまとめる方がはるかに優れています。
それでは、コードをシミュレートして(今はステップ1と2のみを使用します)、何が起こるかを見てみましょう。


import threading
import time
time0=time.time()
def print_ming():
    time.sleep(4)
    print('我拿到了(小明)')

def print_hong():
    time.sleep(3)
    print('我拿到了(小红)')

ming=threading.Thread(target=print_ming)

hong=threading.Thread(target=print_hong)

ming.start()
hong.start()


print('执行完了')
time1=time.time()
print(time1-time0)

ここに写真の説明を挿入

Xiao Ming Xiaohongは、メインプログラムの実行が終了した後に実行を終了したことがわかりました。そこで、ここでは宅配便の兄弟の役割を紹介します。メインプロセスは宅配便の兄弟であり、XiaomingとXiaohongはそれぞれ2つのサブプロセスです。コードにこれらの2つ以上の子プロセスしかない場合は問題ありませんが、メインプロセスも非常に重要であり、実装する機能がいくつかある場合は、非常に面倒です。それを呼ぶのは宅配便を利用するようなものです。兄弟は宅配便の車をより速く運転するので、シャオミンとシャオホンを待たなければなりません。
ここに写真の説明を挿入
したがって、弟も一緒に走っている場合、Xiao MingとXiaohongは宅配便を利用できないため
、詳細な手順使用するまで待つ必要があります(弟、つまりメインスレッドに任せます)


import threading
import time
time0=time.time()
def print_ming():
    time.sleep(4)
    print('我拿到了(小明)')

def print_hong():
    time.sleep(3)
    print('我拿到了(小红)')

ming=threading.Thread(target=print_ming)

hong=threading.Thread(target=print_hong)
ming.setDaemon(True)
ming.start()
hong.setDaemon(True)
hong.start()
ming.join()#让小哥即等等小明也等等小红
hong.join()

print('执行完了')
time1=time.time()
print(time1-time0)

効果は以下の通りです。
ここに写真の説明を挿入

ロックの問題(ロック)(工場の問題(私のアナロジー))

他のことは話さないで、私のニーズについて話しましょう。次のコードのように、プログラムが0から始めて1を追加して1000を取得する1000回を達成できることを願っています。

a = 0
def go():
    global a
    for i in range(1000):
        a+=1
    print(a)
go()

ここで、同時に2回実行する
ようにします。つまり、次のように2000コードを取得します。


import threading
import time
time0=time.time()

a = 0
def go():
    global a
    time.sleep(1)#让程序睡眠一秒便于对比
    for i in range(1000):
        a+=1
    print(a)


def main():
    tx = threading.Thread(target=go)
    tx.setDaemon(True)
    tx.start()

    t1 = threading.Thread(target=go)
    t1.setDaemon(True)
    t1.start()

    t1.join()
    tx.join()


main()
time1=time.time()
print(time1-time0)

結果は次のとおりです。
ここに写真の説明を挿入
目標を達成したようですので、値を1000から1000000に変更しましょう。
ここに写真の説明を挿入
消費者と生産者の関係(わかりません。私が示した例を覚えておいてください。結局のところ、コーディングは専門用語ではありません)
このとき、何かがおかしいことがわかりました。理由により、2回取得する必要がありますが、現在は何が原因かわかりません。
仮定してみましょう。工場には部品を製造している2人の従業員がいます。彼らは、機械に1つの部品を配置する必要があり、機械には1つの場所しかありません。作業者が部品を配置ポートに入れると、機械は1つを梱包します。梱包後、作業員が部品を製造し、機械に梱包したことを証明する製造チケットを受け取ります。しかし、このマシンは、2つのパーツを組み合わせると問題が発生し、1つのパッケージのみがパックされます。
現在の状況も同様で、スレッドの実行時間はランダムです。2つのスレッドが同時に変数を使用し、結果が同じになる場合があります。たとえば、工場の例では、AとBはそれぞれ100パーツで200パーツを処理する必要がありました。上司がチェックしたところ、150個のパッケージしか出ていませんでした。上司は誰かが怠け者だと思っていましたが、AとBは同じことを証明するために200枚の請求書を持っていました。AとBが働いていたとき、彼らは部品を同時に機械に入れ、1つのパッケージだけを梱包しました。
そのため、この状況を回避する例として、マシンをロックする必要があります。その中にパーツがある場合、そのパーツはロックされ、他のパーツは待機しています。
'
lock ' threading.Lock()
ここに写真の説明を挿入
使用して、ボックス内のコードを変更します。
ここで、2人の作業者AとBがマシンNo. 1に対応する場合、BとCはマシン2に対応することに注意してください。したがって、ロックは、マシンがグローバル変数に対応することを意味します。つまり、変数はaで、ロックはロックです
が、変数がbの場合、lock2などの別のロックを設定する必要があります。つまり、1つのマシンが2つのワーカーに対応し、他の2つのワーカーが別のマシンに対応する場合、対応するロックも異なります。

ロックとブロッキングの問題(状態)(工場の問題(私のアナロジー))

消費者と生産者の関係(理解できません。私が示した例を思い出してください。結局のところ、コードの入力は専門用語ではありません)
条件はロックを継承します
が、主にロックとロック解除の方が費用がかかるため、このような条件を使用する理由、一部のプログラムを実行し続ける必要がない場合や、ロックを使用してロックを解除し続ける必要がない場合があります。待機する方法を変更できます。
工場の例で説明を続けますが、それでもこのマシンには問題があります。このマシンは毎回過熱するため、現時点では部品を入れることができません(幸い、このマシンには問題があるかどうかを知らせるアラームがあります)ので、この時点で作業者は待つ必要があります。まず、パーツを持って、マシンが正常になるのを待つことができます。
次に、そのメソッドを紹介します(threading.Condition())
acquire()lock
release()unlock
wait()waiting for
notify()alarm(彼の近くのワーカーにのみ通知します)
notify_all()alarm(すべてのワーカーに通知します)
次に、コードを変更します。関数も変更します。



import threading
import time
time0=time.time()
lock=threading.Condition()
a = 0
def go():
    global a
    time.sleep(1)#让程序睡眠一秒便于对比
    lock.acquire()#上锁
    for i in range(100):
        #执行a加到100
        a+=1
    lock.notify_all()#发警报
    lock.release()#开锁
    print(a)
    print(threading.current_thread())#查看当前线程

def stop():
    global a
    lock.acquire()
    for i in range(100):
        while a<=-20:
            lock.wait()
        a-=1
        #a减1减100次如果减了一百次中有减到-20(线程是随机的不一定会减到-20)
        # 那么就等等,所以如果减到了-20那么最后得到0,或者80(没有到-20),或者0
        #有20次减到了-20其中加了20次还要加减80次。
    lock.release()
    print(a)
    print(threading.current_thread())#查看当前线程


def main():
    tx = threading.Thread(target=go)
    tx.setDaemon(True)
    tx.start()

    t1 = threading.Thread(target=stop)
    t1.setDaemon(True)
    t1.start()

    t1.join()
    tx.join()


main()
time1=time.time()
print(time1-time0)

結果は次のとおりです。
ここに写真の説明を挿入

キュー

主にセキュリティの問題と一部の変数のロックの問題のためです。キュー要素が十分でないかいっぱいになると、前述のグローバル変数と同じように、この変数に書き込むことができることを除いて、自動的にロックされます。複数の値は、グローバルリスト変数と同等です。ただし、この人はスレッドを一時停止して続行するように制御できます。同時に、複数の子スレッドが同時にグローバル変数を呼び出すと、変更量が不安定になります。たとえば、値2は子プロセス1によって割り当てられ、値3は子プロセス2によって割り当てられます。このとき、変数の値が2か3か。スレッドはランダムであり、その状態を知らないため、量子状態です。
したがって、このことを使用して、このキュー内のこの変数の安定性を確保します。変更するたびに、それを書き留めて別の人に渡します。この人には、最初の変更の値を選択する権利があります。これはマルチスレッドクローラーでより一般的に使用されます(500以上を読み取る、マルチスレッドクローラーの例を書く、または書く時間があるまで待つ、とにかく最近は時間がない)
1。これをインポートするのはキューインポートからですPythonに組み込まれたキュー
2これはキュータイプ(要素が先着順)であり、それに応じてLifoQueue(要素が先着順)スタックタイプも必要です。
3.基本的な使用法

q=Queue(4) 设置队列(最大允许几个值)
q.qsize() 查看最大允许几个
q.full() 看一看有没有满
q.empty()看看有没有空,空True,满False
q.put 加元素
q.get() 得到最先加入的元素并删去


例;

from queue import Queue
q=Queue(4)
for i in range(1,5):
    q.put(i)
for i in range(4):
    print(q.get())
print(q.empty())

ここに写真の説明を挿入

基本的にはそれだけです。

おすすめ

転載: blog.csdn.net/FUTEROX/article/details/107471476