Pythonのマルチスレッドの基礎

公式リファレンスドキュメント

https://docs.python.org/zh-cn/3.7/library/threading.html#module-threading

直接スレッドの子スレッドを作成

import threading
import time


def work(internal):
    name = threading.current_thread().name
    print(f"{name} start")
    time.sleep(internal)
    print(f"{name} end")


print("Main: ", threading.current_thread().name)
for i in range(5):
    thread_instance = threading.Thread(target=work, args=(i, ))
    thread_instance.start()

print("Main: end")

ここでは、2つのメインスレッドと子スレッドMainThreadスレッド1、スレッド2は3つのスレッドの合計を生成しました。加えて、我々は、第一の端部は、メインスレッド、実行することが観察
スレッド1、1秒から4秒の各間隔の終わりまでスレッド2の連続ランを。メインスレッドが子スレッドを待たないことをこのショーは、実行の終了前に実行を終了しますが、直接、少し常識を引き抜きました。

スレッドの終了後に、サブメインスレッドの規定

import threading
import time


def work(internal):
    name = threading.current_thread().name
    print(f"{name} start")
    time.sleep(internal)
    print(f"{name} end")


print("Main: ", threading.current_thread().name)
for i in range(5):
    thread_instance = threading.Thread(target=work, args=(i, ))
    thread_instance.start()
    # 规定主线程在子线程后退出 
    thread_instance.join()

print("Main: end")

程度の参加があります。

あなたが私たちのテスト実行時間を踏む場合、あなたはそれが個別に実行されているかどうかを発見することができ、またはマルチスレッド実行では、実行時間は10秒程度だった参加します。
(10 = 1 + 2 + 3 + 4)は、実際に、結合の結果を使用することが正しくない、マルチスレッド動作の意味を失っているように見えます。

どのような、そして、それの本当の意味に参加?
メインスレッドが立ち往生し、サブスレッド、現在はすでにあなたはこのスレッドが完成ランニングを持って.joinを呼び出すまで実行を継続し始めるようになるに参加。
だから、私たちはすることができ、最長のスレッドの1に参加する必要があります。

import threading
import time


now = lambda :time.time()


def work(internal):
    name = threading.current_thread().name
    print(f"{name} start")
    time.sleep(internal)
    print(f"{name} end")


t1 = now()
print("Main: ", threading.current_thread().name)
for i in range(5):
    thread_instance = threading.Thread(target=work, args=(i, ))
    thread_instance.start()
    # 可规定主线程在子线程后退出
    if i == 4:
        thread_instance.join()

print(f"Main: end, Time: {now() - t1}")

もちろん、これは、スレッドがなくなった最初の私たちの知っている、スレッドが戻って完成実行している場合です。
ケースでは、後の未来、完了するまで実行したスレッドそれぞれに参加する必要性を知りません。

私たちは、シナリオを想定しています。ご使用の10個のスレッドを使用して、データを分析することができ、すべてのURLまで待つメインスレッドのニーズが上昇アップ後に撮影されており、100 URLをクロール爬虫類。この時点で、あなたはメインスレッドに参加することができ、最初に立ち往生
実行するすべての10のサブスレッドは、メインスレッドとその後の操作の終わりまで。
私が完了するまで実行するためにどのスレッドがわからない場合は、どのようにそのスレッドを実行した後ですか?この時間は、それが操作を実行するために、各スレッドに参加する必要があります。
この場合、各スレッドは、結合を使用するのが妥当です:

thread_list = []
for _ in range(10):
    thread = threading.Thread(target=xxx, args=(xxx, xxx)) 换行thread.start()
    thread_list.append(thread)

for thread in thread_list:
    thread.join()

作成継承の方法を通じて、マルチスレッド

import threading
import time


class MyThread(threading.Thread):
    def __init__(self, interval):
        super(MyThread, self).__init__()
        self.interval = interval

    def run(self):
        name = threading.current_thread().name
        print(f"{name} start")
        time.sleep(self.interval)
        print(f"{name} end")


print("Main: ", threading.current_thread().name)
for i in range(5):
    thread_instance = MyThread(i)
    thread_instance.start()
    # 可规定主线程在子线程后退出
    # 可规定主线程在子线程后退出
    if i == 4:
        thread_instance.join() 
print("Main: end")

2つの実装の効果は同じです。

デーモンスレッド

メインスレッドが終わるとスレッドの保護者が、完成していないランニングを持っている場合は、そのどの手段、スレッドがデーモンスレッドとして設定されていれば、それはこのスレッドが「重要」であることを意味し、スレッド内のデーモンスレッドと呼ばれる概念があります、
それは最後に強制されます。Pythonでは、私たちはは、setdaemon方法にスレッドがデーモンスレッドすることができます。

import threading
import time


now = lambda:time.time()


def work(internal):
    name = threading.current_thread().name
    print(f"{name} start")
    time.sleep(internal)
    print(f"{name} end")


thread_1 = threading.Thread(target=work, args=(1, ))
thread_2 = threading.Thread(target=work, args=(5, ))
thread_2.setDaemon(True)
thread_1.start()
thread_2.start()

print("Main End.")

ミューテックス

このようなプロセスのような共有リソースのプロセスで複数のスレッド、そこにカウントするグローバル変数の数があり、そして今、我々は複数のスレッドを宣言し、プラス1つのカウントは、各スレッドが、実行されている与えた
のを見てみようどのように効果が次のように、コードが実装されています。

import threading
import time

count = 0


class MyThread(threading.Thread):
    def __init__(self):
        super(MyThread, self).__init__()

    def run(self):
        global count
        temp = count + 1
        time.sleep(0.001)
        count = temp


def main():
    threads = []
    for _ in range(1000):
        thread_ = MyThread()
        thread_.start()
        threads.append(thread_)

    for t in threads:
        t.join()

    print("Final count: ", count)


main()

その方法は、常識によると、最終カウント値を1000にする必要があります。しかし、それは真実ではない、のは、それを実行して見てみましょう。
結果は以下の通りである:
最終カウント:69

これはなぜでしょうか?カウント値が共有されているため、各スレッドがコードの場合、この行をカウント= TEMPカウントの現在値を取得するために実行することができるが、同時にこれらのスレッドまたはいくつかのスレッドは、並列に実行することができる
別のスレッドにそのリード同じことが、いくつかのスレッド数が1だけインクリメントされ、操作が小さすぎて、最終的な結果につながる、力ではないが有力、カウント値を取得するかもしれません。

データのため、同時に複数のスレッドが読み取りまたは修正するのであれば、予期しない結果が表示されます。これを避けるために、我々は同期を達成するために、複数のスレッドを同期する必要があり、
我々は動作するように、データ保護の必要性をロックすることができ、threading.Lockを使用する必要があります。

ロック保護、それは何を意味するのでしょうか?データの前にスレッドは、あなたが解放されるように、他のスレッドがロックされた後に発見されたのでことを、我々は、ダウンし続けることができない、常にロックを待機し、ロックする必要がある、
唯一のロックねじロック放し、他のスレッドが終了したロックデータとメイクの変更、修正に進み、その後、ロックを解除することができます。同時にデータを操作するだけで一つのスレッドこの保証し、複数のスレッドが同時に読み込まれませんと、同じデータを変更し
、最終的な結果は、実行のペアですので。

import threading
import time

count = 0
lock = threading.Lock()


class MyThread(threading.Thread):
    def __init__(self):
        super(MyThread, self).__init__()

    def run(self):
        global count
        # 获取锁
        lock.acquire()
        temp = count + 1
        time.sleep(0.001)
        count = temp
        # 释放锁
        lock.release()


def main():
    threads = []
    for _ in range(1000):
        thread_ = MyThread()
        thread_.start()
        threads.append(thread_)

    for t in threads:
        t.join()

    print("Final count: ", count)


main()

Pythonのマルチスレッドについて

PythonのGILの制限のためには、シングルコアまたはマルチコアの条件のいずれかで、その結果、同時にあなただけのマルチコア並列を活用Pythonはできないマルチスレッドで、その結果、一つのスレッドを実行することができます。
GILフルネームGlobalInterpreterLock、もともとデータのセキュリティと配慮のために設計されたグローバルインタプリタロック、のための中国語の翻訳。次のようにPythonの複数のスレッドでは、各スレッドの実装です。

  • GILを取得
  • コードの実行スレッドに対応
  • GILのリリースは、
    あなたが最初にGILを取得する必要があり、スレッドは実行したい見て、我々はGILパスとして見することができ、Pythonのプロセスでは、GIL一つだけ。スレッドのパスを取得し、実装が許可されていません。
    これはさえ、マルチコアの条件の下で、Pythonのプロセスで複数のスレッドが、同じ時間だけつのスレッドを実行できるためにつながります。

しかし、IO集約型のタスクなど爬虫類のために、この問題はあまりにも素晴らしいではありません。全体に比べためGIL、マルチスレッド動作効率の計算集約型のタスクのために実際にシングルスレッドよりも低くてもよいです。

公開された291元の記事 ウォンの賞賛104 ビュー410 000 +

おすすめ

転載: blog.csdn.net/Enjolras_fuu/article/details/105160584