Python多线程Barrier障碍对象原理与实战详解
本文详解Python中threading.Barrier线程障碍对象的原理与应用。介绍parties、action和timeout等核心参数,解析多线程同步阻塞机制。通过播放器初始化案例演示常规使用与reset重置功能,重点讲解超时导致的BrokenBarrierError异常处理,帮助开发者掌握多线程同步技巧。
Python线程Barrier障碍对象简介
在Python多线程编程中,Barrier被称为障碍对象,也常被称为栅栏或屏障。
一、线程障碍对象Barrier简介
# 导入线程模块
import threading
# 障碍对象barrier
barrier = threading.Barrier(parties, action=None, timeout=None)
parties参数用于设置线程计数器,即记录参与同步的线程数量,也称为线程障碍数量。
action参数是一个可选的可调用函数。当等待的线程数量达到parties设定的障碍数量时,其中一个线程会优先执行action指定的函数,随后其他线程继续执行各自内部的代码逻辑。
timeout参数用于设置默认的超时时间,若等待超过该时间,障碍将进入断开状态。
线程障碍对象Barrier工作原理
二、线程障碍对象Barrier原理
与互斥锁Lock、事件Event或定时器Timer不同,多线程Barrier机制中设置了线程障碍数量parties。如果当前等待的线程数量未达到parties,所有线程将处于阻塞状态;一旦等待线程数量达到该数值,Barrier将唤醒所有等待的线程继续执行。
这一机制可能较为抽象,我们可以通过播放器场景来理解:首先需要一个线程负责播放器初始化(如加载本地文件或获取播放地址),另一个线程负责获取视频画面,还有一个线程负责获取音频声音。只有当初始化、视频和音频三个任务全部完成时,播放器才会开始播放;若其中任意一个线程未完成,播放器将保持阻塞状态,直到所有任务均告完成。
Barrier核心函数解析
三、多线程障碍对象Barrier相关函数介绍
wait(timeout=None)方法用于阻塞当前线程并尝试通过障碍。如果等待的线程数量大于或等于parties,表示障碍已通过,系统将执行action对应函数并继续执行线程内部代码;否则线程将继续等待。若wait(timeout=None)发生超时,障碍将进入断开状态。如果在线程等待期间障碍被断开或重置,此方法会抛出BrokenBarrierError错误,因此务必添加异常处理,具体实现可参考案例一。
reset()方法用于重置线程障碍数量,使其恢复到默认的空状态,即当前阻塞的线程需要重新等待。如果在线程等待期间障碍被断开或重置,此方法同样会引发BrokenBarrierError错误,需注意添加异常处理,具体实现可参考案例二。
Barrier实战案例与异常处理
四、线程障碍对象Barrier使用
1. 案例一:常规使用场景
# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:何以解忧
@Blog(个人博客地址): shuopython.com
@WeChat Official Account(微信公众号):猿说python
@Github:www.github.com
@File:python_arbrier.py
@Time:2019/10/31 21:25
@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
"""
# 导入线程模块
import threading
def plyer_display():
print('初始化通过完成,音视频同步完成,可以开始播放....')
# 设置3个障碍对象
barrier = threading.Barrier(3, action=plyer_display, timeout=None)
def player_init(statu):
print(statu)
try:
# 设置超时时间,如果2秒内,没有达到障碍线程数量,
# 会进入断开状态,引发BrokenBarrierError错误
barrier.wait(2)
except Exception as e: # 断开状态,引发BrokenBarrierError错误
print("等待超时了... ")
else:
print("xxxooooxxxxxooooxxxoooo")
if __name__ == '__main__':
statu_list = ["init ready","video ready","audio ready"]
thread_list = list()
for i in range(0,3):
t = threading.Thread(target=player_init,args=(statu_list[i],))
t.start()
thread_list.append(t)
for t in thread_list:
t.join()
运行输出结果如下:
init ready
video ready
audio ready
初始化通过完成,音视频同步完成,可以开始播放....
xxxooooxxxxxooooxxxoooo
xxxooooxxxxxooooxxxoooo
xxxooooxxxxxooooxxxoooo
注意:当barrier.wait(timeout=None)等待超时时,障碍会进入断开状态并引发BrokenBarrierError错误。为了保证程序的健壮性,建议在实际开发中增加相应的异常处理机制。
2. 案例二:使用reset()重置线程障碍数量
# 导入线程模块
import threading
def plyer_display():
print('初始化通过完成,音视频同步完成,可以开始播放....')
# 设置3个障碍对象
barrier = threading.Barrier(3, action=plyer_display, timeout=None)
def player_init(statu):
while True:
print(statu)
try:
# 设置超时时间,如果2秒内,没有达到障碍线程数量,
# 会进入断开状态,引发BrokenBarrierError错误
barrier.wait(2)
except Exception as e: # 断开状态,引发BrokenBarrierError错误
# print("断开状态... ")
continue
else:
print("xxxooyyyxxxooyyyxxxooyyy")
break
if __name__ == '__main__':
statu_list = ["init ready","video ready","audio ready"]
thread_list = list()
for i in range(0,3):
t = threading.Thread(target=player_init,args=(statu_list[i],))
t.start()
thread_list.append(t)
if i == 1: # 重置状态
print("不想看爱情片,我要看爱情动作片....")
barrier.reset()
for t in thread_list:
t.join()
运行输出结果如下:
init ready
video ready
不想看爱情片,我要看爱情动作片....
init ready
video ready
audio ready
初始化通过完成,音视频同步完成,可以开始播放....
xxxooyyyxxxooyyyxxxooyyy
xxxooyyyxxxooyyyxxxooyyy
xxxooyyyxxxooyyyxxxooyyy
注意:当barrier.wait(timeout=None)等待超时时,障碍会进入断开状态并引发BrokenBarrierError错误。为了保证程序的健壮性,建议在实际开发中增加相应的异常处理机制。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









