배리어(Barrier)는 파이썬에서 제공하는 동기화 기법 중 하나로, 하나 또는 여러 개의 스레드가 미리 정해진 지점에 도달할 때까지 서로를 기다린 후 함께 다음 작업을 진행하도록 만들어 줍니다. 즉, 각 스레드가 도착하는 시점은 달라도 모든 스레드가 배리어 지점에 모일 때까지 대기한 뒤 동시에 출발하는 것입니다.
배리어 객체 생성하기
배리어 객체는 threading.Barrier를 사용하여 생성합니다.
threading.Barrier(parties, action=None, timeout=None)
각 매개변수의 의미는 다음과 같습니다.
parties : 배리어 지점을 통과해야 하는 스레드의 수
action : 스레드들이 해제될 때 그중 하나의 스레드에 의해 호출되는 콜백 함수
timeout : 기본 타임아웃 값.
wait()메서드에 별도의 타임아웃이 지정되지 않은 경우 이 값이 사용됩니다.
Barrier 클래스의 주요 메서드와 속성
Barrier 클래스에서 자주 사용되는 메서드와 속성은 아래 표와 같습니다.
| 번호 | 메서드 및 설명 |
|---|---|
| 1 | parties 공통 배리어 지점에 도달해야 하는 스레드의 수입니다. |
| 2 | n_waiting 현재 배리어 지점에서 대기 중인 스레드의 수입니다. |
| 3 | broken 불리언(Boolean) 값으로, 배리어가 깨진(broken) 상태이면 True, 그렇지 않으면 False입니다. |
| 4 | wait(timeout=None) 호출한 스레드를 배리어에 등록하고, 설정된 스레드 수만큼 모든 스레드가 도착하거나 타임아웃이 발생할 때까지 대기 상태로 블록합니다. timeout 인자가 None이 아닌 값으로 지정된 경우, 초 단위(소수점 이하 포함 가능)의 부동 소수점 숫자여야 합니다. |
| 5 | reset() 배리어를 기본 상태, 즉 빈 상태로 되돌립니다. 이때 배리어에서 대기 중이던 스레드들은 BrokenBarrierError 예외를 받게 됩니다. |
| 6 | abort() 배리어를 강제로 깨진(broken) 상태로 만듭니다. 이로 인해 현재 활성화된 모든 스레드와 이후의 wait() 호출은 BrokenBarrierError와 함께 실패하게 됩니다. |
실전 예제 코드
barrierThread.py
from random import randrange
from threading import Barrier, Thread
from time import ctime, sleep
num = 4
# 4개의 스레드가 모두 이 배리어를 통과해야 해제됩니다.
b = Barrier(num)
names = ['India', 'Japan', 'USA', 'China']
def player():
name = names.pop()
sleep(randrange(2, 5))
print('%s reached the barrier at: %s \n' % (name, ctime()))
b.wait()
threads = []
print("Race starts now…")
for i in range(num):
threads.append(Thread(target=player))
threads[-1].start()
"""
아래 반복문은 메인 스크립트가 계속 진행되기 전에
모든 스레드가 종료될 때까지 기다리도록 합니다.
"""
for thread in threads:
thread.join()
print("All Reached Barrier Point!")위 예제에서는 네 개의 스레드가 각각 무작위 시간(2~5초)만큼 대기한 뒤 배리어에 도착합니다. 마지막 스레드가 도착하는 순간 네 스레드가 모두 함께 해제되며 프로그램이 종료 메시지를 출력합니다.
실행 결과
Race starts now… India reached the barrier at: Fri Jan 18 14:07:44 2019 China reached the barrier at: Fri Jan 18 14:07:44 2019 Japan reached the barrier at: Fri Jan 18 14:07:46 2019 USA reached the barrier at: Fri Jan 18 14:07:46 2019 All Reached Barrier Point!
결과를 보면 각 스레드가 배리어에 도착한 시각이 서로 다르지만, 모든 스레드가 도착한 이후에야 일괄적으로 통과된 것을 확인할 수 있습니다. 이처럼 배리어는 여러 스레드의 작업 진행 시점을 특정 지점에서 맞춰야 하는 상황에서 매우 유용하게 활용됩니다.