3

私はスレッドモジュールを理解しようとしているpythonの初心者です。Python 2.7 を使用しています。Python での with_statement の動機の 1 つは、次のコード パターンであることが挙げられました。

with threading.Lock():
        //User defined function in a new thread

正しく理解しているかどうかはわかりませんが、最初の想定では、このコードは、子スレッドが完了すると解放されるメインスレッドのロックを取得する必要があります。それでもこのスクリプト

from __future__ import print_function
import threading
import time
import functools
#import contextlib
#Thread module for dealing with lower level thread operations.Thread is limited use Threading instead.

def timeit(fn):
    '''Timeit function like this doesnot work with the thread calls'''
    def wrapper(*args,**kwargs):
        start = time.time()
        fn(*args,**kwargs)
        end = time.time()
        threadID = ""
        print ("Duration for func %s :%d\n"%(fn.__name__ +"_"+ threading.current_thread().name ,end-start))
    return wrapper

exitFlag = 0

@timeit
def print_time(counter,delay):
    while counter:
        if exitFlag:
            thread.exit()
        time.sleep(delay)
        print("%s : %s_%d"%(threading.current_thread().name,time.ctime(time.time()),counter))
        counter -= 1

class Mythread(threading.Thread):
    def __init__(self,threadID,name,counter,delay):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
        self.delay = delay

    def run(self):
        print("Starting%s\n" % self.name)
        print_time(self.counter, self.delay)
        print("Exiting%s\n" % self.name)


if __name__ == '__main__':
    '''
    print_time(5, 1)
     threadLock = threading.Lock()
     threads = []
     thread1 = Mythread(1,"Thread1",5,1)
     thread2 = Mythread(2,"Thread2",5,2)
     thread1.start()
     thread2.start()
     threads.append(thread1)
     threads.append(thread2)
     for t in threads:
         t.join()
    '''
    thread1 = Mythread(1,"Thread1",5,1)
    thread2 = Mythread(2,"Thread2",5,2)
    lock = threading.Lock()
    with lock:
        thread1.start()
        thread2.start()

    print("Exiting main thread ")

次の出力が生成されます。

StartingThread1

StartingThread2

Exiting main thread 
Thread1 : Sat May 04 02:21:54 2013_5
Thread1 : Sat May 04 02:21:55 2013_4
Thread2 : Sat May 04 02:21:55 2013_5
Thread1 : Sat May 04 02:21:56 2013_3
Thread1 : Sat May 04 02:21:57 2013_2
Thread2 : Sat May 04 02:21:57 2013_4
Thread1 : Sat May 04 02:21:58 2013_1
Duration for func print_time_Thread1 :5

ExitingThread1

Thread2 : Sat May 04 02:21:59 2013_3
Thread2 : Sat May 04 02:22:01 2013_2
Thread2 : Sat May 04 02:22:03 2013_1
Duration for func print_time_Thread2 :10

ExitingThread2

このような with_statement でロックが機能しない理由、または概念を完全に誤解している理由を理解するのを手伝ってください。

4

1 に答える 1

12

あなたの存在lockは基本的に何もしません。他のスレッドがそれを参照していないため、誰かがどこかをブロックする可能性はありません。できることは、数マイクロ秒を無駄にすることだけです。したがって、この:

lock = threading.Lock()
with lock:
    thread1.start()
    thread2.start()

... は以下とほとんど同じです:

time.sleep(0.001)
thread1.start()
thread2.start()

そして、それはあなたが望んでいるものではないと確信しています。

スレッドを強制的に順次実行する場合、最も簡単な方法は、スレッドを使用しないことです。

または、スレッドを使用する必要がある場合は、スレッドが終了するのを待ってから次のスレッドを開始します。

thread1 = Mythread(1,"Thread1",5,1)
thread2 = Mythread(2,"Thread2",5,2)
thread1.start()
thread1.join()
thread2.start()
thread2.join()

外部からの助けなしにスレッド自体をシリアライズさせたい場合は、共有できるロックをスレッドに与える必要があります。例えば:

class Mythread(threading.Thread):
    def __init__(self,threadID,name,counter,delay,lock):
        threading.Thread.__init__(self)
        self.lock = lock
        # ...
    def run(self):
        with self.lock:
            # ...

今、それらを呼び出すには:

lock = threading.Lock()
thread1 = Mythread(1,"Thread1",5,1, lock)
thread2 = Mythread(2,"Thread2",5,2, lock)
thread1.start()
thread2.start()
# ...
thread1.join()
thread2.join()

これで、各スレッドが起動すると、ロックを取得しようとします。with1 つは成功し、もう 1 つは (そのステートメントを終了することによって) 最初のロックが終了するまでブロックされます。


スレッドをシリアライズしたくない場合は、メイン スレッドが他のすべてのスレッドの完了を待機するようにするだけです。必要なのはjoin. まさにそのjoinためです。他に何も追加する必要はありません。


本当にやりたい場合は、スレッドをデーモン化し、代わりに同期オブジェクトを待つことができます。ロックでこれを行う簡単な方法は考えられませんが、BoundedSemaphore、またはを使用するとかなり簡単になるはずConditionです (ただし、条件を 2 回待つ必要があります)。しかし、これを行うのは非常にばかげているので、なぜそうしたいのかわかりません。

于 2013-05-04T00:41:35.153 に答える