Python: threading.Barrier
import time, logging, typing, threading, random, datetime FORMAT = '{asctime} {levelname} {process} {processName} {threadName} {thread} {message}' logging.basicConfig(level=logging.INFO, style='{', format=FORMAT, datefmt='%Y-%m-%d %H:%M:%S') def vacuity(barrier: threading.Barrier): logging.info(f'n_waiting = {barrier.n_waiting}') try: # The return value is an integer in the range 0 to parties-1, different to each thread. This can be used to select a thread to do some special housekeeping n_waiting = barrier.wait() logging.warning(f'barrier.wait() = {n_waiting}') except threading.BrokenBarrierError as e: logging.info(f'broken barrier in {threading.current_thread()}') logging.info(f'BrokenBarrierError = {e}') # If an action was provided to the constructor, one of the threads will have called it prior to being released. Should this call raise an error, the barrior is put into the broken state barrier = threading.Barrier(parties=3, action=lambda: print('action', threading.current_thread())) for b in range(10): threading.Thread(target=vacuity, name=f'vacuity-{b}', args=(barrier,)).start() threading.Event().wait(1)
三个一波,凑齐运行
import time, logging, typing, threading, random, datetime FORMAT = '{asctime} {levelname} {process} {processName} {threadName} {thread} {message}' logging.basicConfig(level=logging.INFO, style='{', format=FORMAT, datefmt='%Y-%m-%d %H:%M:%S') def vacuity(barrier: threading.Barrier): logging.info(f'n_waiting = {barrier.n_waiting}') try: # The return value is an integer in the range 0 to parties-1, different to each thread. This can be used to select a thread to do some special housekeeping n_waiting = barrier.wait() logging.warning(f'barrier.wait() = {n_waiting}') except threading.BrokenBarrierError as e: logging.info(f'broken barrier in {threading.current_thread()}') # If an action was provided to the constructor, one of the threads will have called it prior to being released. Should this call raise an error, the barrior is put into the broken state barrier = threading.Barrier(parties=3, action=lambda: print('action', threading.current_thread())) for b in range(10): match b: case 2: barrier.abort() case 6: barrier.reset() threading.Thread(target=vacuity, name=f'vacuity-{b}', args=(barrier,)).start() threading.Event().wait(1)
import time, logging, typing, threading, random, datetime FORMAT = '{asctime} {levelname} {process} {processName} {threadName} {thread} {message}' logging.basicConfig(level=logging.INFO, style='{', format=FORMAT, datefmt='%Y-%m-%d %H:%M:%S') def vacuity(barrier: threading.Barrier, n: int): logging.info(f'barrier.n_waiting = {barrier.n_waiting}, barrier.broken = {barrier.broken}') try: if n < 3: n_waiting = barrier.wait(timeout=2) else: if n == 6: barrier.reset() n_waiting = barrier.wait() logging.warning(f'barrier.wait() = {n_waiting}') except threading.BrokenBarrierError as e: logging.critical(f'broken barrier in {threading.current_thread()}') # If an action was provided to the constructor, one of the threads will have called it prior to being released. Should this call raise an error, the barrior is put into the broken state barrier = threading.Barrier(parties=3, action=lambda: print('action', threading.current_thread())) for b in range(10): threading.Thread(target=vacuity, name=f'vacuity-{b}', args=(barrier, b)).start() threading.Event().wait(4)