如何与Python同步运行Thread?

时间:2016-10-07 20:05:30

标签: python multithreading

我需要使用3个线程依次使用Python打印数组项。

每个线程将打印一个数组项。

我需要让线程休眠几秒钟,然后打印该项目。

此功能将执行N次。该N值由用户给出。

必须在特定订单上打印项目,这意味着我必须以某种方式阻止其他线程执行而前一个未完成。 我一直在尝试很多不同的解决方案,但我无法弄清楚如何让它发挥作用。

我尝试使用信号量,锁定和事件,但同步没有成功。在所有情况下,它将根据time.sleep随机打印序列,而不是序列本身。如何阻止线程执行该函数并检查前一个线程是否已完成以允许序列工作?

我应该使用哪种工具才能使其正常工作?任何帮助表示赞赏。

class myThread(threading.Thread):
def __init__(self, group=None, target=None, name=None,
             args=(), kwargs=None, verbose=None):
    super(myThread,self).__init__()
    self.target = target
    self.name = name
    return

def run(self):
    while True:
        if not q.empty():
            semaphore.acquire() 
            try:
                time_sleep = random.randrange(0,10) 
                print "thread " + self.name + ". Dormir por " + str(time_sleep) + " segundos"
                time.sleep(time_sleep)
                print cores[int(self.name)]
                if int(self.name) == len(cores) - 1:
                    item = q.get()
                    print 'Executou sequencia ' + str(item + 1) + ' vezes. Ainda irá executar ' + str(q.qsize()) + ' vezes'
                    e.set()
            finally:
                semaphore.release()
                if int(self.name) != len(cores) - 1:
                    e.wait()
    return

if __name__ == '__main__':
    for i in range(2):
        q.put(i)

    for i in range(3):
        t = myThread(name=i)
        t.start()

2 个答案:

答案 0 :(得分:1)

这方面有很多种方法。一个简单的方法是使用共享的Queue数字。

每个线程可以长时间睡眠,在唤醒时从队列中取出一个数字并打印出来。它们将按照它们被推入队列的顺序出现。

如果您的数字是连续的,或者可以动态生成,您也可以使用共享计数器as described in this answer在恒定内存中执行此操作。

答案 1 :(得分:0)

如果您不关心订单,可以使用锁来同步访问。但是,在这种情况下,事件列表如何。每个线程都有自己的事件槽,并在完成后将其交给列表中的下一个事件。这个方案可以通过返回一个上下文管理器来实现,这样你就不需要显式释放了。

import threading

class EventSlots(object):

    def __init__(self, num_slots):
        self.num_slots = num_slots
        self.events = [threading.Event() for _ in range(num_slots)]
        self.events[0].set()

    def wait_slot(self, slot_num):
        self.events[slot_num].wait()
        self.events[slot_num].clear()

    def release_slot(self, slot_num):
        self.events[(slot_num + 1) % self.num_slots].set()


def worker(event_slots, slot_num):
    for i in range(5):
        event_slots.wait_slot(slot_num)
        print('slot', slot_num, 'iteration', i)
        event_slots.release_slot(slot_num)


NUM = 3

slots = EventSlots(NUM)

threads = []

for slot in range(NUM):
    t = threading.Thread(target=worker, args=(slots, slot))
    t.start()
    threads.append(t)

for t in threads:
    t.join()