2013-05-04 53 views
1

我是一個嘗試瞭解線程模塊的Python的noob。 我使用的動機蟒蛇2.7.One在蟒蛇with_statement被給了是隨着聲明和python線程

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

我不知道如果我理解正確的話代碼的模式,但我最初的設想是這樣的代碼應該AQUIRE鎖在子線程完成後釋放的mainthread上。 然而,這個腳本

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或有我徹底誤解了concept.I很困惑,爲什麼我得到直接打印(「退出主線程」),甚至通過定義鎖定

+0

創建一個你不與任何其他線程共享的鎖通常沒有意義。你希望鎖能保護你不受這些傷害? – abarnert 2013-05-04 00:38:11

+0

我所試圖做的,是繼續這種說法 \t打印( 「退出主線程」) 在此之後: \t與鎖: \t \t thread1.start() \t \t thread2.start() 現在這作品時,我明確地調用 \t \t thread1.join() \t \t thread2.join() 但我會更喜歡使用with_statement,因爲它看起來更乾淨。 – Rahuketu86 2013-05-04 00:39:17

+0

附註:您不是在線程上調用'join',也不是將它們設置爲'daemon = True'。這是非法的。它會在某些情況下工作(但是在不同平臺上有不同的情況!),但是你不應該依賴它。 – abarnert 2013-05-04 00:42:58

回答

8

您現有的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() 

現在,當每個線程啓動時,它會嘗試獲取鎖。一個會成功,另一個會阻止,直到第一個鎖完成(通過退出其with聲明)。


如果你不想要序列化的線程,你只是想主線程等待所有其他線程完成......所有你需要的是join。這正是join的用途。沒有必要添加任何其他東西。


如果您確實想要,您可以將線程守護進程並等待同步對象。我想不出一個簡單的方法來實現這個鎖定,但它應該很容易與BoundedSemaphore,或Condition(雖然你必須等待兩次)。但這是一件非常愚蠢的事情,所以我不確定你爲什麼想要。

+0

哪裏可以做 預: \t與鎖: \t \t // F(io_peration1) \t \t // F(io_operation2) \t F(上產生的輸出文件的處理) – Rahuketu86 2013-05-04 01:02:10

+0

我的代碼反覆其中遇到這種圖案我爲此在每一項任務: \t任務1: \t \t與鎖: \t \t \t // F(io_peration1) \t \t \t // F(io_operation2) \t \t \t F(上產生的輸出files_level1處理) \t任務2: \t \t與鎖: \t \t \t // F(1級io_peration文件) \t \t \t // F( io_operation 1級文件) \t \t \t F(處理生成輸出files_level2) – Rahuketu86 2013-05-04 01:04:41

+0

我們正在努力實現一個插件架構,我可以把一些Task1.py Task2.py 在插件目錄 所以我想把這個抽象爲一個可以調用循環中所有任務的獨立函數。 \t 我有點蟒蛇新手,所以我不熟悉整個api.I將探索更多關於 setDaemon.But感謝您的答覆。 – Rahuketu86 2013-05-04 01:05:07