简体   繁体   English

使用两个队列同步线程

[英]Synchronize threads using two queues

Assume that I have a pool of threads. 假设我有一个线程池。 This pool of threads uses two queues q1 and q2 . 该线程池使用两个队列q1q2 It reads from q1 and writes new items on q2 . 它从q1读取并在q2上写入新项目。 When q1 is empty, we swap the two queues q1, q2, = q2, q1 and we repeat the process until both are empty. q1为空时,我们交换两个队列q1, q2, = q2, q1然后重复该过程,直到两个都为空。 In order to synchonize the threads, I use another queue which contains only one item and I remove this item at the end of the process. 为了同步线程,我使用了另一个仅包含一个项目的队列,并在流程结束时删除了该项目。

I think this is a very stupid way to do it. 我认为这是一种非常愚蠢的方法。 Any suggestion for improvement? 有什么改善的建议吗?

A very nice simple example is on the docs but with only one queue. 文档上有一个很好的简单示例,但只有一个队列。 My solution does not look very nice, if it is correct: 我的解决方案看起来不是很好,如果正确的话:

global flag
global lock
global barrier
global q1
global q2
global q
while True:
    if q1.empty():
        flag = False
        barrier.wait() # wait for all the theads to reach this point.
        # execute the code of swapping queues only once
        with lock:
            if not flag:
                flag = True
                if q2.empty():
                    q.get()
                    q.task_done()
                else:
                    q1, q2 = q2, q1

    process_items_in_q1()

I think your aproach works. 我认为您的方法行得通。 Here are two others that you may or may not find better: 这是另外两个您可能会或可能不会发现的更好的地方:

  1. you can use only one queue and push N markers to separate the "levels", where N is the number of threads. 您只能使用一个队列并按N个标记来分隔“级别”,其中N是线程数。 When a thread reads a marker it just calls barrier.wait(). 当线程读取标记时,它仅调用barrier.wait()。 This should be enough if the goal is just to ensure that all N threads call barrier.wait() between the levels. 如果目标只是确保所有N个线程在级别之间调用barrier.wait(),这应该足够了。

  2. or alternatively, you can simplify a bit the code posted above: use 2 plain lists instead of 2 queues. 或者,您也可以简化上面的代码:使用2个普通列表而不是2个队列。 All threads pop from list1 and append to list2 , which doesn't need the special care in the logic of Queue. 所有线程都从list1弹出并追加到list2 ,在Queue逻辑中不需要特别注意。 Also, if the "levels" are each relatively large, you might simply repeat for each level the whole code that creates threads and waits until they are all done. 另外,如果每个“级别”都相对较大,则可以为每个级别重复创建线程的整个代码,并等待它们全部完成。 This would make the one-level-at-a-time logic even more obvious. 这将使一次一级的逻辑更加明显。

(Finally, as usual, note that so far you don't gain any processing power by using threads in Python: there's the GIL.) (最后,像往常一样,请注意,到目前为止,使用Python中的线程并没有获得任何处理能力:这里有GIL。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM