2013-05-04 3 views
1

Я новичок в python, пытаясь понять модуль потоковой передачи. Я использую питон 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

+0

То, что я пытаюсь сделать здесь перейти к этому заявлению \t печати ("Выход основного потока") после этого: \t с замком: \t \t thread1.start() \t \t thread2.start() сейчас это работает, когда я называю в явной форме \t \t thread1.join() \t \t thread2.join() , но я предпочитаю использовать with_statement, как она выглядит более чистой. – Rahuketu86

+0

В качестве побочного примечания: вы не называете 'join' в потоках и не устанавливаете их в' daemon = True'. Это незаконно. Он будет работать в некоторых ситуациях (но разные на разных платформах!), Но вы никогда не должны полагаться на него. – abarnert

ответ

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 // е (io_peration1) \t \t // е (io_operation2) \t ф (обработка на генерируемых выходных файлов) – Rahuketu86

+0

Мой код встречает эту модель несколько раз, когда я сделать это в каждой задаче: \t Задача 1: \t \t с замком: \t \t \t // е (io_peration1) \t \t \t // F (io_operation2) \t \t \t F (обработка на генерируемой выходной files_level1) \t Задача 2: \t \t с замком: \t \t \t // F (io_peration Level1 файлов) \t \t \t // F (io_operation level1 files) \t \t \t f (обработка сгенерированного выходного файла files_level2) – Rahuketu86

+0

Мы пытаемся создать архитектуру плагина, где я могу разместить Task1.py Task2.py в каталоге плагинов Итак, я хотел бы отвлечь это как отдельную функцию, которая может вызывать всю задачу в цикле. \t Я своего рода новичок с питоном, поэтому я еще не знаком со всем api.I рассмотрю немного больше о setDaemon. Но спасибо за ваши ответы. – Rahuketu86

Смежные вопросы