Python 线程同步的三种方式

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

方式一:Event

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

import logging
import time
from threading import Thread, Event

logging.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()  # 会一直阻塞直到事件被set
    while 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, Condition

logging.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, Barrier

logging.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 正在工作...

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值