Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
&引用;Python线程屏障“;为什么这段代码有效?有没有更好的方法?_Python_Multithreading_Barrier - Fatal编程技术网

&引用;Python线程屏障“;为什么这段代码有效?有没有更好的方法?

&引用;Python线程屏障“;为什么这段代码有效?有没有更好的方法?,python,multithreading,barrier,Python,Multithreading,Barrier,我已经搜索了python屏障,但相关问题很少。我仍然对barrier.wait()感到困惑,甚至我的代码也能工作 我利用python屏障实现了这样一个函数:一个主线程和n个子线程。在每一轮中,主线程等待所有子线程完成当前工作,然后所有线程进入下一轮,直到满足某些条件。因此,我发现barrier适合实现这个函数,这是我的主线程代码 def superstep(self): workers = [] barrier = threading.Barrier(self.num_work

我已经搜索了python屏障,但相关问题很少。我仍然对barrier.wait()感到困惑,甚至我的代码也能工作

我利用python屏障实现了这样一个函数:一个主线程和n个子线程。在每一轮中,主线程等待所有子线程完成当前工作,然后所有线程进入下一轮,直到满足某些条件。因此,我发现barrier适合实现这个函数,这是我的主线程代码

 def superstep(self):
    workers = []
    barrier = threading.Barrier(self.num_workers+1)
    for vertex in self.vertices:
        worker = Worker(vertex, barrier)
        workers.append(worker)
        worker.start()

    while self.flag:
        barrier.wait()
        self.distributeMessages()
        self.count += 1
        print ("superstep: ", self.count)
        self.flag = self.isTerminated()

    for worker in workers:
        worker.flag = False

    for worker in workers:
        worker.join()
  • 第一个“for”循环创建名为worker并存储在workers列表中的n个线程
  • “while”循环是等待其他子线程的主线程,当self.flag为False时中断
  • 第二个“for”循环用于在每个辅助线程(子线程)中将标志设置为False,告诉它们退出循环
  • 这是我的工人班

    class Worker(threading.Thread):
        def __init__(self, vertex, barrier):
            threading.Thread.__init__(self)
            self.vertex = vertex
            self.flag = True
            self.barrier = barrier
    
        def run(self):
            while self.flag:
                self.barrier.wait()
                do something
    
    代码运行良好,所有线程都可以连接()。但正如我所看到的,当所有线程调用wait()时,所有线程都将同时释放。如果主线程从while循环中断,而所有其他线程都在正确地等待它,那么在这种情况下,第二个“for”循环是无用的,子线程将永远不会加入()


    那么这段代码是如何工作的,除了引发BrokenBarrierError外,还有其他方法可以退出屏障吗?此外,如果我在第二个“for”循环中添加一些代码,打印一些信息或其他内容,则过程会被阻止。我猜一定有一些子线程处于wait()状态,并且没有机会检查标志,因此它们无法从线程的run()中退出。

    如果您不想使用
    中止
    可以在每个线程中调用两个
    Barrier.wait
    。这将把操作分成两部分。在第一部分中,工作线程将完成其工作,主线程将更新标志状态。然后在第二部分中,每个线程将检查标志状态,并在必要时退出循环

    在代码级别上,它看起来像这样:

    # Main
    def superstep(self):
        workers = []
        barrier = threading.Barrier(self.num_workers+1)
        for vertex in self.vertices:
            worker = Worker(vertex, barrier)
            workers.append(worker)
            worker.start()
    
        while self.flag:
            barrier.wait()
            self.distributeMessages()
            self.count += 1
            print ("superstep: ", self.count)
            self.flag = self.isTerminated()
            for worker in workers:
                worker.flag = self.flag
            barrier.wait()
    
        for worker in workers:
            worker.join()
    
    # Worker
    def run(self):
        while self.flag:
            self.barrier.wait()
            # do something
            self.barrier.wait() 
    
    你可以打电话

    self.barrier.abort()
    

    要在第二个for循环后释放等待的worker,并在worker的
    run()
    方法中捕获
    brokenbarrieerror

    您可以在第二个for循环后调用
    barrier.abort()
    ,释放等待的worker。@Gribouillis感谢您的回复。barrier.abort()引发BrokenBarrierError,它会妨碍我的代码执行,因此我想知道是否有更好的方法。您可以在worker中捕获BrokenBarrierErrorthreads@Gribouillis谢谢这是正确的方法。请原谅我以前不熟悉异常处理。经过几分钟的学习,这个问题已经很清楚了。好吧,我把这个作为一个答案,所以你可以接受它。谢谢,我以前接受的答案也很漂亮。