Python で Java の CyclicBarrier を実装してみる


マルチスレッドのデザインパターンを引き続き復習します。
前記事 : Python で Java の CountDownLatch を実装してみる

実は、Python 3.2 からバリアオブジェクトがサポートされているので、こんな劣化版を作る意味はないのですが、勉強勉強。

バリアって何よ

並列コンピューティングにおけるバリア(英: Barrier)とは、同期方法の一つであり、ソースコード中でスレッドやプロセスがある箇所で停止し、他の全てのスレッドプロセスがバリアに到達するまで進行しないようなものを示す。

from Wikipedia

CountDownLatch との違い

待機を解除する条件が、スレッド同士の待ち合わせと関係がないのが、CountDownLatch。 関係するのが、CyclicBarrier。極端な話、CountDownLatch はある 1 つのスレッドの中で、何回もカウントダウンをしても良い。

サンプルコード

# coding:utf-8

import threading

class CyclicBarrier(object):
    def __init__(self, count):
        assert count > 0, "count は 1 以上の値を与えてください。入力値[{}]".format(count)
        self.count = count
        self.condition = threading.Condition()

    def await(self):
        self.condition.acquire()

        self.count -= 1
        while self.count > 0:
            self.condition.wait()

        self.condition.notifyAll()
        self.condition.release()

    def broken(self):
        if(self.count > 0):
            return False
        else:
            return True

def worker(barrier, n):
    print("Worker: {}".format(n))
    barrier.await()

if __name__ == "__main__":
    # 5 回 barrier.await() が呼ばれたらバリアは破壊される
    count = 5
    barrier = CyclicBarrier(count)

    for i in range(count-1):
        thread = threading.Thread(target=worker, args=(barrier, i))
        thread.start()

    barrier.await()

    if(barrier.broken()):
        print("バリアは壊れました")

実行結果

Worker: 0
Worker: 1
Worker: 2
Worker: 3
バリアは壊れました