ホームページ  >  記事  >  バックエンド開発  >  Python マルチスレッドにおけるブロッキング (結合) とロック (Lock) の使用に関する誤解の分析

Python マルチスレッドにおけるブロッキング (結合) とロック (Lock) の使用に関する誤解の分析

不言
不言オリジナル
2018-04-27 10:53:312924ブラウズ

この記事は主にすべての人に向けて詳しく説明します この記事では、Python マルチスレッドにおける join と lock のブロックに関する誤解について紹介します。興味のある方は、

メインスレッドのブロックの間違った使い方について

join

Thread.join ( ) この機能は、メインスレッドをブロックすることです。つまり、子スレッドが返さない場合、メインスレッドは子スレッドが戻るのを待ってから実行を継続します。

join はループ内で start と組み合わせて使用​​することはできません。以下はエラー コードです。コードは 5 つのスレッドを作成し、ループを使用してスレッドをアクティブ化し、アクティブ化後にメイン スレッドをブロックします。

1.メインスレッドは start 関数を通じてスレッド 1 を起動し、スレッド 1 は計算を実行します。

2. start 関数はメインスレッドをブロックしないため、スレッド 1 が演算を実行している間、メインスレッドは join 関数を下向きに実行します。 join の実行後、メインスレッドはスレッド 1 によってブロックされます。スレッド 1 が結果を返す前に、メインスレッドは次のサイクルを実行できません。

4. スレッド 1 の計算が完了したら、メインスレッドのブロックを解除します。メインスレッドは次のサイクルに入り、スレッド 2 をアクティブにし、スレッド 2 によってブロックされます...

このようにして、同時であるはずだった 5 つのスレッドがここで順次キューになり、効率が向上していることがわかります。

join


の正しい使用法は、
start

関数と

join

関数をそれぞれ処理するために2つのループを使用します。

threads = [Thread() for i in range(5)]
for thread in threads:
  thread.start()
  thread.join()

time。 .sleep はデバッグ用の join を置き換えます 以前、いくつかのプロジェクトで、join の代わりに time.sleep を使用してメインスレッドを手動でブロックするそのようなコードを見たことがあります。終了できませんでした。

threads = [Thread() for i in range(5)]
for thread in threads:
  thread.start()
for thread in threads:
  thread.join()

スレッドロック(threading.Lock)について


シングルコアCPU+PILにはまだロックが必要ですか?

非アトミック操作

count = count + 1

理論的には、スレッドアンセーフです。

3 つのスレッドを使用して上記の操作を同時に実行し、グローバル変数 count の値を変更し、プログラムの実行結果を確認します。

結果が正しい場合は、スレッドが存在しないことを意味します。競合します。次のコードを使用してテストします

for thread in threads:
  thread.start()
while 1:
  if thread_num == 0:
    break
  time.sleep(0.01)

実行結果:

count=275552

実際、各実行の結果は異なり、間違っています。これは、シングルコア CPU+ であることを証明しています。 PIL は依然としてスレッドの安全性を保証できないため、ロックする必要があります。

ロック後の正しいコード:

# -*- coding: utf-8 -*-
import threading
import time
count = 0
class Counter(threading.Thread):
  def __init__(self, name):
    self.thread_name = name
    super(Counter, self).__init__(name=name)
  def run(self):
    global count
    for i in xrange(100000):
      count = count + 1
counters = [Counter('thread:%s' % i) for i in range(5)]
for counter in counters:
  counter.start()
time.sleep(5)
print 'count=%s' % count

結果:

count=500000

ロックのグローバルな性質に注意してください

これは単純な Python 構文の問題ですが、ロジックが複雑な場合に発生します。無視される可能性があります。

ロックが複数のサブスレッドで共有されていることを確認してください。つまり、Thread のサブクラス内にロックを作成しないでください。
以下は

エラーコードです
​​

# -*- coding: utf-8 -*-
import threading
import time
count = 0
lock = threading.Lock()
class Counter(threading.Thread):
  def __init__(self, name):
    self.thread_name = name
    self.lock = threading.Lock()
    super(Counter, self).__init__(name=name)
  def run(self):
    global count
    global lock
    for i in xrange(100000):
      lock.acquire()
      count = count + 1
      lock.release()


counters = [Counter('thread:%s' % i) for i in range(5)]

for counter in counters:
  counter.start()

time.sleep(5)
print 'count=%s' % count


関連する推奨事項:

Pythonスレッドの同期ロックの詳細な説明

以上がPython マルチスレッドにおけるブロッキング (結合) とロック (Lock) の使用に関する誤解の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。