Python的同步原语

python协程与异步并发,同步与阻塞,异步与非阻塞,Python异步IO、协程与同步原语介绍,协程的优势和劣势 python多线程:协程与异步并发,同步与阻塞,异步与非阻塞,Python异步IO、协程与同步原语介绍,协程的优势和劣势 阅读详情

前言

在多线程编程中,同步原语(synchronization primitives)是确保线程安全和正确执行的关键。Python 提供了一些基础的同步原语,用于协调线程之间的访问和操作。Python的同步原语包括 Lock、RLock、Semaphore、Event 和 Condition,接下来简单介绍一下他们的使用

Lock

Lock(锁)是最简单也是大家最熟悉的同步原语,相信所有的编程语言中,大伙都接触过并且使用过。它允许一个线程独占对共享资源的访问,防止其他线程在同一时间访问该资源。

import threading

lock = threading.Lock()

count = 0

def add():
    for _ in range(10000):
        
        global count,lock
        lock.acquire()
        count += 1
        lock.release()
threads = []
for _ in range(100):
    thread = threading.Thread(target=add)
    threads.append(thread)
    thread.start()
for t in threads:
    t.join()
print(count)

在上面代码中,我们对一个变量进行加一操作,然后在100各线程中执行,每个线程执行操作时,先获取锁,执行之后在释放锁,这样就避免了竞态条件,确保了最终的计数值是正确的。在测试中你可以去掉锁试试,多测试几次,看是不是每次都能获得到预想的结果。

RLock

RLock(可重入锁)是 Lock 的扩展,它允许同一线程多次获得锁,而不会导致死锁。

import threading

rlock = threading.RLock()

def rlock_test():
    with rlock:
        print("Thread", threading.current_thread().name, "acquired the lock")
        with rlock:
            print("Thread", threading.current_thread().name, "acquired the lock again")

threads = [threading.Thread(target=rlock_test) for i in range(5)]
for t in threads:
    t.start()
    
for t in threads:
    t.join()
   

如果你运行了上面代码,你可以发现所有线程都正常执行了,说明在执行rlock_test()函数时,并没有进入死锁状态,你可以奖RLock换成Lock试试。

Semaphore

Semaphore(信号量)允许多个线程同时访问共享资源。它维护一个计数器,只有在计数器大于零时,线程才能访问资源,并在访问后递减计数器。 信号量在所有语言中,都是一个重要同步原语。

import threading
import time

semaphore = threading.Semaphore(3)

def semaphore_test():
    with semaphore:
        print("Thread", threading.current_thread().name, "is accessing the resource\n")
        # 模拟资源访问时间
        time.sleep(1)

threads = [threading.Thread(target=semaphore_test) for _ in range(12)]

t1 = time.time()
for t in threads:
    t.start()

for t in threads:
    t.join()
interval = time.time() - t1
print(interval)

我们把Semaphore初始化为3,然后执行12个线程,在我的电脑中执行完差不多4s,如果换成了Lock锁,执行时间是12s多,你可以好好理解一下,是不是差不多4个批次?一个批次执行了3个线程?这就是上面说的,信号量允许多个线程同时访问共享资源,记住这一点很重要。

Event

Event(事件)用于线程间通信。一个线程可以设置事件,其他线程可以等待事件的发生。比如在开发中,可能需要等待某个线程完成后,再去执行其他的线程,这个时候可以使用Event

import threading
import time


event = threading.Event()
def wait_for_event():
    print(threading.current_thread().name, "is waiting for the event\n")
    event.wait()
    print(threading.current_thread().name, "got the event\n")

def trigger_event():
    print(threading.current_thread().name, "setting the event\n")
    event.set()

threads = [threading.Thread(target=wait_for_event) for _ in range(5)]
trigger_thread = threading.Thread(target=trigger_event)

for t in threads:
    t.start()

time.sleep(10)
trigger_thread.start()

for t in threads:
    t.join()
trigger_thread.join()

运行上面代码,你可以看到有5个线程打印出了第一个函数中的第一个print,等待trigger_thread执行后,才会继续执行完函数。

Condition

Condition(条件变量)用于复杂的线程同步场景,它通常与锁一起使用,以便线程可以等待某些条件满足。

import threading
import time


condition = threading.Condition()

def consumer(i):
    with condition:
        print(f'Consumer{i} is waiting')
        condition.wait()
        print(f"Consumer{i} got the signal")

def producer():
    with condition:
        print("Producer is setting the condition")
        time.sleep(10)
        print("Producer notify all")
        condition.notify_all()
consumer_threads = []
consumer_threads =[threading.Thread(target=consumer, args=(i,)) for i in range(5)]
producer_thread = threading.Thread(target=producer)

for t in consumer_threads:
    t.start()

producer_thread.start()

for t in consumer_threads:
    t.join()
producer_thread.join()

运行上面代码,可以看到如下结果

Consumer0 is waiting
Consumer1 is waiting
Consumer2 is waiting
Consumer3 is waiting
Consumer4 is waiting
Producer is setting the condition
Producer notify all
Consumer2 got the signal
Consumer4 got the signal
Consumer1 got the signal
Consumer3 got the signal
Consumer0 got the signal

consumer_threads 中的线程等待producer_thread执行**condition.notify_all()**后,才会继续执行。

总结

Python 和其他语言哟杨,同步原语为多线程编程提供了强大的工具,以确保线程安全和正确执行。通过理解和使用这些同步原语,开发者可以有效地避免竞态条件(race conditions)和死锁问题,从而编写出更加可靠和健壮的多线程应用程序。在实际开发中,可能80%的情景之下使用Lock就足够了,但其他的几种同步原语对象我们也要了解,在一些特定情况下对我们很有帮助

Python异步编程中常用的同步原语函数 这样,coro协程就会继续执行。wait()方法用于等待条件的发生,会释放锁并使协程进入等待状态,直到被其他协程通过notify()或notify_all()方法唤醒。notify()方法用于唤醒等待的协程中的一个,而notify_all()方法用于唤醒所有等待的协程。wait()方法用于等待条件的发生,会释放锁并使协程进入等待状态,直到被其他协程通过notify()或notify_all()方法唤醒。notify()方法用于唤醒等待的协程中的一个,而notify_all()方法用于唤醒所有等待的协程。 阅读详情

相关推荐

Python 线程同步原语大全:Lock、RLock、Semaphore、Condition、Event实战

本文介绍了Python多线程编程中的同步机制。首先分析了Python线程的局限性(GIL),然后通过银行转账示例展示了竞态条件问题。接着详细讲解了锁原语的工作原理、银行转账实现、常见陷阱(如死锁)及避免方法。还介绍了可重入锁RLock的特点及其在递归函数中的应用场景。最后探讨了信号量的概念及其在资源管理中的实际应用,如连接池管理。文章结合代码示例,帮助开发者理解如何在多线程环境中确保数据一致性。

静水深流 359

Python多线程同步教程

概述 多线程给我们带来的好处是可以并发的执行多个任务,特别是对于I/O密集型的业务,使用多线程,可以带来成倍的性能增长。 可是当我们多个线程需要修改同一个数据,在不做任何同步控制的情况下,产生的结果往往是不可预料的,比如两个线程,一个输出hello,一个输出world,实际运行的结果,往往可能是一个是hello world,一个是world hello。 python里提供了多个用于控制多线程同步的

piapiada的博客 609

VINS-Mono 代码详细解读——IMU预积分的残差、Jacobian和协方差 processIMU()+intergrationBase类+imu_factor.h

IMU离散中值预积分 1.1、IMU模型 测量值:加速度计a^、陀螺仪w^, 加上了bias游走和随机白噪声。 真实值:加速度计a、陀螺仪w。 实际情况下,可以获得测量值a^和w^,需要反推真实值。一般忽略随机游走高斯噪声n w=w^-bg; a=qwb(a^-ba)-gw; 1.2、连续时间IMU运动模型,积分 PVQ(两帧之间) 将第k帧和第k+1帧所有的IMU进行积...

try_again_later的博客 9266

Python协程(asyncio)(四)同步原语

asyncio 同步原语被设计为与 threading 模块的类似,但有两个关键注意事项:asyncio 原语不是线程安全的,因此它们不应被用于 OS 线程同步 (而应当使用 threading);这些同步原语的方法不接受 timeout 参数;请使用 asyncio.wait_for() 函数来执行带有超时的操作。

1377

如何在R中高效安装ropls及其依赖包

本文详细介绍了在R语言中高效安装ropls包及其依赖的完整流程。作为Bioconductor生物信息学分析包,ropls的安装需通过BiocManager管理器进行。文章提供了标准安装步骤、跨系统避坑指南及安装后验证方法,帮助用户解决R版本、编译环境和网络镜像等常见问题,确保代谢组学数据分析工具顺利部署。

efc123456的博客 908

LTE随机接入实战:如何通过PRACH前导码优化小区覆盖半径(附计算公式)

本文深入探讨了LTE网络中PRACH前导码格式对小区覆盖半径的关键影响。通过解析不同前导码格式(如Format 0-3)的物理参数与覆盖能力,提供了核心计算公式与实战Python脚本,指导网络工程师根据覆盖需求、环境多径和容量等因素,科学选择前导码格式以优化边缘用户接入成功率,实现精准的网络规划与优化。

qq_27496129的博客 575

聊聊 Python 中的同步原语,为什么有了 GIL 还需要同步原语

在前面的文章中我们介绍了 Python 中的全局解释器锁 GIL,我们知道 GIL 可以保证在多线程场景下同一时刻只有一个线程运行,但是并不能保证线程安全

Lorin 洛林的后端技术小站 1029

CentOS8静默安装Oracle11.2.0.1

背景 新安装oracle,用静默安装方式就不需要安装图形界面了,省时省力。 前期准备工作与图形化安装一样,如创建用户|用户组、环境变量、内核参数、创建目录等. 可参考图形化安装,链接:https://blog.youkuaiyun.com/heroicpoem/article/details/104229369 环境 平台 版本 操作系统 centOS 8 Oracle 11gR2 1.响应文件 响应文件的内容就是图形化安装时手工设置的选项内容。 解压后,database/response/db

heroicpoem的专栏 4518

Python中基本同步原语的使用

Python中的同步原语--锁 from atexit import register from random import randrange from threading import Thread, Lock, current_thread from time import ctime, sleep class CleanOutputSet(set): def __st...

aslongas2015的博客 373

基于多智能体架构的AI自动化渗透测试平台PentAGI部署与实战

自动化渗透测试是网络安全领域提升效率、应对复杂威胁的关键技术。其核心原理在于通过程序化脚本或智能系统模拟攻击者行为,对目标系统进行安全评估。该技术能显著降低人工重复劳动,实现7x24小时持续监控与测试,其价值在于将安全专家从繁琐的扫描、信息收集中解放出来,专注于高级威胁分析与策略制定。在实际应用中,自动化渗透测试广泛应用于企业安全自评估、红蓝对抗演练及DevSecOps流程。本文聚焦于一个名为PentAGI的先进平台,它采用多智能体(Multi-Agent)系统架构,集成了知识图谱和向量数据库,实现了从侦察

weixin_30294295的博客 606

STM32单片机:驱动ADS1115四个通道全开程序

本文介绍了德州仪器(TI)的ADS1115高精度16位模数转换器(ADC)及其应用实现。该芯片具有16位分辨率、可编程增益放大器(PGA)和低功耗特性,支持±0.256V至±6.144V量程。文章提供了完整的C语言驱动代码,包括初始化、配置寄存器读写、单次/连续转换模式设置、电压值读取等功能实现。代码通过I2C接口与ADS1115通信,支持多通道选择和不同PGA设置,可实现高精度模拟信号采集。该方案适用于需要精密测量的嵌入式系统,如传感器数据采集等应用场景。

weixin_42122070的博客 689

python线程同步原语--源码阅读

前面两篇文章,写了python线程同步原语的基本应用。下面这篇文章主要是通过阅读源码来了解这几个类的内部原理和是怎么协同一起工作来实现python多线程的。 相关文章链接:python同步原语--线程锁 python--线程同步原语 一、关于Condition类 Condition...

weixin_30755393的博客 211

修改 Alist 密码时报错?看看这个坑怎么解决!

启动服务后,再修改密码”。以后再遇到类似问题,先检查服务是否正常运行,说不定就能少踩不少坑。如果还有其他 Alist 的问题,欢迎在评论区留言交流~

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1154

Python编程:为什么使用同步原语

简单互斥→Lock嵌套锁需求→RLock资源池限制→Semaphore线程间通知→Event或Condition复杂协调逻辑→Condition。

林十一npc的博客 1313

【WRF-GHG 教程第一期】概述(Overview)

概述(Overview)

WW、forever的博客 510

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Python 并发编程:同步原语精要指南

本教程系统解析Python并发编程中的**核心同步机制**,涵盖互斥锁(Lock)、可重入锁(RLock)、信号量(Semaphore)、事件(Event)、条件变量(Condition)和屏障(Barrier)六大原语。通过20+个**实战代码示例**和10种**应用场景分析**,详解各原语的工作原理、适用场景与最佳实践,并提供死锁预防策略和高级同步模式(生产者-消费者模型、读写锁模式)。教程包含**性能对比矩阵**、**决策流程图**和**GIL环境下同步要点**,帮助开发者构建安全高效的并发系统。

YAnt的博客 1230

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Python Asyncio 库之同步原语常用函数详解

内部会维护一个计数器,无论何时进行获取或释放,它都会递增或者递减(但不会超过边界值),当计数器归零时,就会进入到锁的逻辑,但是这个锁逻辑会在计数器大于0的时候释放j,它的用法如下:`方法执行异常导致锁一直被卡住的场景,通常情况下这能解决大部分的问题,但是如果遇到错误的封装时,我们需要亲自处理异常,并执行锁的唤醒。发现计数器已经为0了,则会使当前协程进入等待状态,直到某个协程离开这个代码块时,计数器会递增一,并唤醒等待的协程,使其能够进入代码块中继续执行。这两个方法符合同步原语中对资源的争夺和释放,但是。

Everly_的博客 2133

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Python协程:asyncio同步原语

在 Python 的异步编程中,`asyncio` 提供多种同步原语,用于协程之间的协调与资源共享。本文聚焦于四种核心工具:`Lock` 用于互斥访问共享资源,`Event` 实现任务间的信号传递,`Condition` 协调任务在特定条件下运行,而 `Semaphore` 限制并发任务的数量。这些工具能帮助开发者高效解决竞争条件、优化任务调度,为异步应用提供强大的控制能力。

merlon学习笔记 991

python多线程同步机制_python同步原语--线程锁

多线程锁是python多种同步原语中的其中一种。首先解析一下什么是同步原语,python因为GIL(全局解析锁)的缘故,并没有真正的多线性。另外python的多线程存在一个问题,在多线程编程时,会出现线程同时调用共同的存储空间而导致错误的出现(即‘竞态行为’)。虽然许多专家建议python开发者在处理并发的时候弃用多线程而用多进程,但是在I/O操作这种短时间的操作上(通常GIL锁在这段时间内已经释...

weixin_39517289的博客 182

python 同步PHP,python中线程同步原语的代码示例

本篇文章给大家带来的内容是关于python中线程同步原语的代码示例,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。Threading模块是python3里面的多线程模块,模块内集成了许多的类,其中包括Thread,Condition,Event,Lock,Rlock,Semaphore,Timer等等。下面这篇文章主要通过案例来说明其中的Event和Segmaphore(Bound...

weixin_35419195的博客 149

[Python3高阶编程] - 多线程并发编程二:同步原语

同步原语是否可重入主要用途适用场景复杂度Lock❌ 否互斥访问保护简单共享变量⭐RLock✅ 是递归/嵌套加锁类方法内部多次调用加锁函数⭐⭐Condition✅(基于 RLock)等待-通知生产者-消费者、任务队列⭐⭐⭐⭐Semaphore❌限制并发数连接池、资源池⭐⭐Event❌一次性信号启动同步、简单通知⭐🔑核心思想LockRLock解决“互斥”问题ConditionEvent解决“协作”问题Semaphore解决“限流”问题在 Python 多线程中,

1402

[Python3高阶编程] - 异步编程深度学习指南二: 同步原语

在异步编程中,多个协程可能同时访问共享资源,这会导致竞态条件(race condition)等问题。asyncio 提供了一系列同步原语来协调协程之间的执行,确保数据一致性和正确的执行顺序。重要提示:asyncio 的同步原语与 threading 模块的对应原语类似,但专为异步环境设计,不能在同步代码中使用,也不能与 threading 原语混用。原语主要用途并发控制数据传递复杂度Lock互斥访问1个协程❌⭐Event信号通知无限制❌⭐Semaphore限流控制N个协程❌⭐⭐。

1642

python多线程编程—同步原语入门(锁Lock、信号量(Bounded)Semaphore)

python多线程编程—同步原语入门(锁Lock、信号量(Bounded)Semaphore) 摘录python核心编程 一般的,多线程代码中,总有一些特定的函数或者代码块不希望(或不应该)被多个线程同时执行(比如两个线程运行的顺序发生变化,就可能造成代码的执行轨迹或者行为不相同,或者产生不一致的数据),比如修改数据库、更新文件或其他会产生竞...

weixin_34363171的博客 230
上一篇: Python的进程、线程、协程总结篇
下一篇: git版本回退
双木林的林
博客等级 码龄11年 127粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值