2
import threading
import Queue

q = Queue.Queue()
class Worker( threading.Thread ):
    def __init__( self, q ):
        threading.Thread.__init__( self )
        self.q = q

    def run( self ):
        while True:
            print '%s waiting for data' % self.getName()
            data = self.q.get()
            print '%s data fetched from queue %s' % ( self.getName(), data )
            if data == 'shutdown':
                print '%s shutting down in %s' % ( self.getName(), self )
                return
            print '%s received a message: %s' % ( self.getName(), data )

    def stop( self ):
        self.q.put( "shutdown" )

#        self.join()  # If I uncomment this line, then sometimes the program does not complete.


def broadcast_event( data ):
    q.put( data )

t1 = Worker( q )
t2 = Worker( q )
t1.start()
t2.start()
broadcast_event( "first event" )
broadcast_event( "second event" )

t1.stop()
t2.stop()

Python でスレッドを理解しようとしていますが、マルチスレッド キューの例で行き詰まっています。私がやろうとしていること:-

  1. 1 つのキュー オブジェクトを使用して 2 つのスレッドを作成する
  2. ここで、2 つの異なるデータ エントリをキューに入れます (broadcast_event関数を使用) 。
  3. ここで、stop メソッドには、スレッドをメイン プログラムに戻すコメント行があります。

しかし、このself.join行のコメントを外すと、プログラムがハングアップして永久に実行されます。ただし、を削除するとself.join、完全に機能します。

結合を利用しようとしている方法に問題があるかどうかを理解したいです。

4

2 に答える 2

3

問題は、両方のスレッドが同じキューを使用することです。デッドロックのシナリオは次のとおりです。

  1. メインスレッドが送信'shutdown'するt1.stop()
  2. t2'shutdown'から読み取るq
  3. t1新しいメッセージを永久に待機しているメイン スレッドが参加します。

これを解決するには、2 つのキューを作成するか、最初の 2 つのshutdownメッセージを実行してから 2 つの結合を実行します。

于 2013-04-16T12:20:04.687 に答える
1

問題は、1 つのキューを使用する 2 つのスレッドがあることです。メッセージをキューに入れると、どのスレッドがそれを消費するputかわかりません。を呼び出してキューに追加すると、意図したスレッドとは限らず、いずれかのスレッドによって消費される可能性があります。stop()"shutdown"

その結果、別のスレッドが終了し、join間違ったスレッドを実行している可能性があります。

考えられる解決策は、最初にshutdownキューに N 回 (N = スレッドの数) 入れてから、それらすべてを結合することです。

for i in range(N):
  q.put("shutdown")
for t in threads:
  t.join()

より優れた、より堅牢な解決策は、シャットダウン メッセージをキューに渡さないようにすることです。そのためにアトリビュートを使用しself.should_stopて、 でこのアトリビュートを定期的にチェックできますrun

于 2013-04-16T12:25:18.067 に答える