" Python线程障碍"为什么这段代码有效并且有更好的方法吗?

时间:2016-12-11 06:53:01

标签: python multithreading barrier

我搜索过python障碍,但很少有相关问题。我仍然对barrier.wait()感到困惑,甚至我的代码都有效。

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

 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()
  1. 第一个' for' loop创建n个名为worker的线程并存储在列表worker中。
  2. ' while' loop是等待其他子线程的主线程,并在self.flag为False时中断。
  3. 第二个' for' loop用于在每个worker(子线程)中将flag设置为False,告诉他们退出循环。
  4. 这是我的工人阶级。

    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
    

    代码运行良好,所有线程都可以join()。但是当我查看python barrier时,当所有线程调用wait()时,所有线程将同时释放。如果主线程从while循环中断开并且所有其他线程正好等待它,在这种情况下,第二个' for'循环是无用的,子线程永远不会加入()。

    那么这个代码是如何工作的,还有其他方法可以退出障碍而不是提高BrokenBarrierError吗?此外,如果我在第二个代码中添加一些代码,那么对于'循环,打印一些信息或其他东西,程序被阻止。我想必须有一些子线程在wait()中并且没有机会检查标志,所以它们不能从线程的run()退出。

2 个答案:

答案 0 :(得分:1)

如果您不想使用abort,则可以在每个帖子中对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() 

答案 1 :(得分:1)

你可以打电话

private void dataGridView1_CellEndEdit(object sender, KeyEventArgs e)
{ 
    int col = dataGridView1.CurrentCell.ColumnIndex;
    int row = dataGridView1.CurrentCell.RowIndex;

    if (col < dataGridView1.ColumnCount - 1)
    {
        col++;
    }
    else
    {
        col = 0;
        row++;
    }

    if (row == dataGridView1.RowCount)
        dataGridView1.Rows.Add();

    dataGridView1.CurrentCell = dataGridView1[col, row];
}

private void Form1_Load(object sender, EventArgs e)
{   
    dataGridView1.AllowUserToAddRows = false;
    dataGridView1.Rows.Add();
}

在第二个for循环后释放等待的worker,并在worker self.barrier.abort() 方法中捕获BrokenBarrierError