2009-08-04 7 views
3

次のコードでは、スレッドによってpickledListが使用されており、グローバルスコープに設定されていることがわかります。グローバルスコープの変数:スレッドによってピックアップされる前にその値が変更できますか?

スレッドが使用していた変数が最終的なwhileループの下のどこかに動的に設定されていた場合、スレッドが使用する前にその値が変更される可能性がありますか?ループに値を動的に設定してスレッドに送信し、スレッドが使用する前に値が変更されていないことを確認しますか?

import pickle 
import Queue 
import socket 
import threading 

someList = [ 1, 2, 7, 9, 0 ] 
pickledList = pickle.dumps (someList) 

class ClientThread (threading.Thread): 
    def run (self): 
     while True: 
     client = clientPool.get() 
     if client != None: 
      print 'Received connection:', client [ 1 ] [ 0 ] 
      client [ 0 ].send (pickledList) 
      for x in xrange (10): 
       print client [ 0 ].recv (1024) 
      client [ 0 ].close() 
      print 'Closed connection:', client [ 1 ] [ 0 ] 


clientPool = Queue.Queue (0) 

for x in xrange (2): 
    ClientThread().start() 

server = socket.socket (socket.AF_INET, socket.SOCK_STREAM) 
server.bind (('', 2727)) 
server.listen (5) 

while True: 
    clientPool.put (server.accept()) 

編集:ここでは

は私の問題のより良い例です。

from threading import Thread 
class t (Thread): 
    def run(self): 
     print "(from thread) ", 
     print i 

for i in range(1, 50):  
    print i 
    t().start() 

がどのように私はそのはもはやにバインドされたような方法でスレッドにiに値を渡すことができます:あなたはこれを実行すると、時々、値がいくつかがスキップさせる、スレッドを出力することができる彼らの前に変更しますこの変数は、iに格納されている値が変更された場合、スレッドが処理している値には影響しません。

+0

これらは、同じソースリストを参照する全く異なる質問です。最初の質問で私はスコープを理解していませんでした。この質問では、スレッドに渡される変数のデータを保護する方法を理解していません。 – Ryan

+0

"スレッド内で値を動的に設定してスレッドに送信し、スレッドが使用する前にその値が変更されないことを確認するにはどうすればよいですか? それはどういう意味ですか?値はスレッドがアクセスした後でなければ変更できませんか? – wbg

+0

のいずれか、またはスレッドに値を送信する必要があります。新しいスコープで終了し、元の値を変更するとスレッドが使用している値に影響しません。 – Ryan

答えて

3

オプション1:あなたのrunメソッドが呼び出されます

ClientThread(arg1, arg2, kwarg1="three times!").start() 

、その場合には:あなたが呼び出すスレッドインスタンスによって

run(arg1, arg2, kwarg1="three times!") 

インスタンス化されるときには、各スレッドに引数を渡すことができますstart()。変更可能なオブジェクト(dicts、lists、instances)を関数に渡す必要がある場合は、ではなく、というグローバル変数を再割り当てする必要があります。

オプション2:あなたはClientThreadオブジェクトにインスタンス変数を設定することができます。

myThread.setMyAttribute('new value') 

オプション2を使用すると、メソッドが何をするかに依存するなど、レース条件を警戒する必要があります。 Lockを使用すると、スレッドからデータを書き込んだり、スレッドにデータを読み込んだりするたびに良いアイデアです。

オプション3:runが最初に呼び出されたときにグローバルを取得し、ローカルにコピーを保存

run(self): 
    localVar = globalVar # only for immutable types 
    localList = globalList[:] # copy of a list 
    localDict = globalDict.copy() # Warning! Shallow copy only! 

オプション1スレッドが指定された値は、その存続期間中に変更する必要はありませんならば行くための正しい方法です、値を変更する必要がある場合はオプション2。オプション3はハックです。一般的には、不変オブジェクト(文字列、数値、タプル)が値と変更可能なオブジェクト(辞書、リスト、クラスのインスタンス)でを渡されることはPythonで覚えておく必要があり、周りの変数/値を渡すことに関して

はでを渡されます参照

したがって、文字列、数値またはタプルを変更しても、以前にその変数に渡されたインスタンスには影響しません。ただし、dict、list、またはinstanceを変更すると影響します。変数を別のオブジェクトに再割り当てしても、以前に与えられた値には影響しません。

グローバル変数は、変更される可能性のある値には使用しないでください。基本的に、あなたの例は間違ったやり方です。

+0

私にそこにbaringのおかげで:)非常に有用な答え。 – Ryan

+0

すべてクリアされましたか? – wbg

+0

あなたの答えは完璧ですが、別の質問が出ます。私はオプション1を使用していますが、キューを使用しているときにこれらの値をスレッドに渡す方法はわかりません。 – Ryan

関連する問題