我们使用多线程的目的通常是并发的运行单独的操作,但有时候也需要在两个或多个线程中同步操作。在Python中,线程同步有多种方式,包括EventConditionBarrier

方式一:Event

调用者可以用set() 和clear() 方法控制这个标志,其他线程可以使用wait() 暂停,直到这个标志被设置

import logging
import time
from threading import Thread, Eventlogging.basicConfig(level=logging.DEBUG, format='%(levelname)s-%(asctime)s-%(message)s')def wait_for_start_work(e_start_work: Event, name: str):logging.debug(f'{name} 等待工作...')e_start_work.wait()  # 会一直阻塞直到事件被setwhile e_start_work.is_set():logging.debug(f'{name} 正在工作...')time.sleep(1)else:logging.debug(f'{name} 下班喽!!!!')def wait_for_start_work_timeout(e_start_work: Event, name: str):logging.debug(f'{name} 等待工作...')event_is_set = e_start_work.wait(timeout=1)     # 等待最多1秒if not event_is_set:logging.debug(f'{name} 还不通知工作,我自己先干了。。')else:logging.debug(f'{name} 正在工作...')if __name__ == '__main__':e = Event()for i in range(2):t = Thread(target=wait_for_start_work, args=(e, f'员工{i}'))t.start()t_xiaowang = Thread(target=wait_for_start_work_timeout, args=(e, f'负责的小王'))t_xiaowang.start()time.sleep(2)logging.info('领导说: 开始工作了!!!')e.set()time.sleep(2)logging.info('领导说: 下班了!!!')e.clear()

结果

DEBUG-2022-06-24 10:14:07,076-员工0 等待工作...
DEBUG-2022-06-24 10:14:07,076-员工1 等待工作...
DEBUG-2022-06-24 10:14:07,077-负责的小王 等待工作...
DEBUG-2022-06-24 10:14:08,091-负责的小王 还不通知工作,我自己先干了。。
INFO-2022-06-24 10:14:09,077-领导说: 开始工作了!!!
DEBUG-2022-06-24 10:14:09,077-员工0 正在工作...
DEBUG-2022-06-24 10:14:09,077-员工1 正在工作...
DEBUG-2022-06-24 10:14:10,086-员工0 正在工作...
DEBUG-2022-06-24 10:14:10,086-员工1 正在工作...
INFO-2022-06-24 10:14:11,085-领导说: 下班了!!!
DEBUG-2022-06-24 10:14:11,101-员工0 下班喽!!!!
DEBUG-2022-06-24 10:14:11,101-员工1 下班喽!!!!

方式二:Condition

Condition使用了一个共享资源锁,允许多个线程等待资源的更新。

import logging
import time
from threading import Thread, Conditionlogging.basicConfig(level=logging.DEBUG, format='%(levelname)s-%(asctime)s-%(message)s')def wait_for_start_work(c_start_work: Condition, name: str):logging.debug(f'{name} 等待工作...')with c_start_work:c_start_work.wait()  # 一直等待直到收到通知logging.debug(f'{name} 正在工作...')def wait_for_start_work_timeout(c_start_work: Condition, name: str):logging.debug(f'{name} 等待工作...')with c_start_work:c_start_work.wait(timeout=1)  # 等待最多1秒logging.debug(f'{name} 还不通知工作,我自己先干了。。')if __name__ == '__main__':c = Condition()for i in range(2):t = Thread(target=wait_for_start_work, args=(c, f'员工{i}'))t.start()t_xiaowang = Thread(target=wait_for_start_work_timeout, args=(c, f'负责的小王'))t_xiaowang.start()time.sleep(2)with c:  # 这里使用with来获得与Condition关联的锁,也可以显示的使用acquire()和release()方法logging.info('领导说: 开始工作了!!!')c.notify_all()  # 通知wait状态的所有线程# c.notify(2)   # 通知2个wait状态的线程

结果

DEBUG-2022-06-24 10:39:00,615-员工0 等待工作...
DEBUG-2022-06-24 10:39:00,616-员工1 等待工作...
DEBUG-2022-06-24 10:39:00,616-负责的小王 等待工作...
DEBUG-2022-06-24 10:39:01,630-负责的小王 还不通知工作,我自己先干了。。
INFO-2022-06-24 10:39:02,628-领导说: 开始工作了!!!
DEBUG-2022-06-24 10:39:02,628-员工0 正在工作...
DEBUG-2022-06-24 10:39:02,629-员工1 正在工作...

方式三:Barrier

Barrier会建立一个集合点,当指定数量的线程到达此点后才会放行

import logging
import time
import threading
from threading import Thread, Barrierlogging.basicConfig(level=logging.DEBUG, format='%(levelname)s-%(asctime)s-%(message)s')def wait_for_start_work(b_start_work: Barrier):logging.debug('{} 等待其他人到齐。。'.format(threading.current_thread().name))b_start_work.wait()  # 会一直阻塞直到被放行logging.debug('{} 正在工作...'.format(threading.current_thread().name))if __name__ == '__main__':b = Barrier(3)  # 三个线程的集合点for i in range(6):t = Thread(target=wait_for_start_work, name=f'员工{i}',args=(b, ))t.start()time.sleep(1)

结果

DEBUG-2022-06-24 11:01:18,710-员工0 等待其他人到齐。。
DEBUG-2022-06-24 11:01:19,726-员工1 等待其他人到齐。。
DEBUG-2022-06-24 11:01:20,738-员工2 等待其他人到齐。。
DEBUG-2022-06-24 11:01:20,739-员工2 正在工作...
DEBUG-2022-06-24 11:01:20,739-员工1 正在工作...
DEBUG-2022-06-24 11:01:20,739-员工0 正在工作...
DEBUG-2022-06-24 11:01:21,755-员工3 等待其他人到齐。。
DEBUG-2022-06-24 11:01:22,768-员工4 等待其他人到齐。。
DEBUG-2022-06-24 11:01:23,768-员工5 等待其他人到齐。。
DEBUG-2022-06-24 11:01:23,768-员工5 正在工作...
DEBUG-2022-06-24 11:01:23,768-员工3 正在工作...
DEBUG-2022-06-24 11:01:23,768-员工4 正在工作...

Python 线程同步的三种方式相关推荐

  1. Python线程同步的5种方式

    问题的引入 import threading total = 0def add():global totalfor i in range(1000000):total += 1def desc():g ...

  2. unix c线程同步的三种方法:互斥量、读写锁以及条件变-xhb8413-ChinaUnix博客

    unix c线程同步的三种方法:互斥量.读写锁以及条件变-xhb8413-ChinaUnix博客 unix c线程同步的三种方法:互斥量.读写锁以及条件变 2012-03-30 14:42:38 分类 ...

  3. Java线程同步的几种方式

    Java线程同步的几种方式 1.使用synchronized关键字  它的工作是对同步的代码加锁,使得每一次只能有一个线程进入同步块,从而保证线程间的安全性.  synchronized关键字的用法: ...

  4. Python 发送 email 的三种方式

    Python发送email的三种方式,分别为使用登录邮件服务器.使用smtp服务.调用sendmail命令来发送三种方法 本文原文自米扑博客:Python 发送 email 的三种方式 Python发 ...

  5. python实现单例模式的三种方式及相关知识解释

    python实现单例模式的三种方式及相关知识解释 模块模式 装饰器模式 父类重写new继承 单例模式作为最常用的设计模式,在面试中很可能遇到要求手写.从最近的学习python的经验而言,singlet ...

  6. 一心多用多线程-线程创建的三种方式

    第一次了解java线程机制,记录一下线程启动的三种方式. 1.通过继承Thread类调用一个线程 public class Thread1 extends Thread{@Overridepublic ...

  7. 【Python】Python创建虚拟环境的三种方式

    Python创建虚拟环境的三种方式比较 Python创建虚拟环境的三种方式 首先:为什么需要虚拟环境? Pipenv vs Virtualenv vs Conda 1. Virtualenv 2. P ...

  8. python列表追加的三种方式对比

    python列表追加的三种方式分别为:+, extend(), append() +是直接将两个列表拼凑在一起,并生成新的列表 extend()是将另一个列表的值插入已有列表中,并不会生成新的列表 a ...

  9. JUC-多线程(5.获得线程的第三种方式)学习笔记

    文章目录 获得线程的第三种方式 : Callable接口 1. 前言 1. 获得多线程的方法几种? 2. 以下两种获得线程的方式的异同 2. 使用 1. 重写 call 方法 2.创建线程 3.获取返 ...

最新文章

  1. LCD: 2D-3D匹配算法
  2. 收藏,7个学习Python编程的最佳开源库!
  3. QQ“远程协助”文字输入技巧
  4. Response文件下载
  5. boost::log::to_log_manip用法的测试程序
  6. C++学习攻略,怎样学好C++语言?
  7. 小程序执行运行过程原理_分享 | 还在焦虑等成绩?成绩小助手了解下
  8. @hotmail.com 账户添加别名,重命名到@outlook.com 一系列问题,顺道附上个人解决方法
  9. movelast对数据记录数有要求吗_客户验厂,电脑坏了,考勤记录数据可以自动生成找回来吗?...
  10. 红米note10 pro刷机
  11. 如何免费获取国外硕博学位论文全文资源
  12. gif透明背景动画_在找gif制作app?分享一个GIF制作神器,视频、图片通通可以变GIF...
  13. java 穷举 排列组合_穷举排列组合列表
  14. 定理在数学中的简写形式_初中数学定义、定理汇总
  15. 记录vue使用bable将es6转译为es5
  16. 基于软路由连接上网的相关配置
  17. 2022G2电站锅炉司炉考试题及在线模拟考试
  18. VUE :class 动态class方法
  19. 有时间和基础可以考HCIE吗?付出的回报值得吗?
  20. 小样本关系分类:STAD: Self-Training with Ambiguous Data for Low-Resource Relation Extraction Extraction

热门文章

  1. arcgis字段计算器python_ARCGIS中字段计算器的使用说明
  2. 新唐单片机 ICP 史上最全教程
  3. 数据可视化 数据可视化看板项目一:(1)模拟实时数据 -使用MYSQL的事件建立动态模拟数据,每秒更新一次 (1)
  4. SQL SERVER中SQL格式化插件——SQL Pretty Printer
  5. 矩阵初等变换的“打洞技巧”与“分块矩阵的行列式公式”
  6. visualVM 介绍 (一)
  7. c语言(http://c.biancheng.net/view/1714.html)
  8. 番茄工作法基础操作手册
  9. Cased by: java.lang.ClassNotFoundException: com.google.common.util.concurrent.SettableFuture
  10. 青岛大学开源OJ平台搭建