返回顶部
首页 > 资讯 > 后端开发 > Python >python线程同步原语--源码阅读
  • 768
分享到

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

线程源码python 2023-01-30 22:01:25 768人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

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

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

相关文章链接:python同步原语--线程 

                      python--线程同步原语                            

 

一、关于Condition

Condition的用法:

用来记录线程的状态变量

查看Condition的源码,会看到作者给开发者提供的文档说明。‘Class that implemets a condition variable’写得很明白,这是一个用来记录线程状态的类。

 

1. Condition对象初始化

从这段代码可以看出,Condition使用了threading模块的Rlock类,关于Rlock的用法可以看我之前写的一篇文章python同步原语--线程锁 。在对象初始化的同时,将Rlock的请求锁和释放锁方法赋给了内部的self.acquire和self.release对象方法。当初始化对象同时初始化这两个方法,也就是说,每个对象在实例化的时候都会实例一个新的可重入锁(RLock)。这样可以避免不同对象(condition实例对象)间对类中共享方法的争夺,避免出现死锁的问题。

 

 

这段代码非常的重要。如果熟悉python的上下文管理的朋友应该一看就明白,这是上下文管理中的进入和退出操作。当在调用with时,程序会自动调用_ _enter_ _方法,在程序执行完毕,退出此上下文环境时,自动调用_ _exit_ _方法。那么在这里的_ _enter_ _和_ _exit_ _方法分别有什么用呢?通过阅读源码发现,前者是调用了Rlock的acquier方法(获取锁),而后者调用了Rlock的release方法(释放锁)。在下面我会继续讲这两个方法在类中的作用。

 

2. wait()方法

源码中对wait()方法的定义是‘Wait  untified  or  until  a  timeout  occurs’。意思是阻塞等待知道有提示(notify)或者超时时间(timeout)的到达。

 

再看看wait()函数的内部逻辑

_is_owned()方法是判断此Condition对象是否有获取到锁,如果没有获取到锁(可能是可重入锁的获取次数已经达到预定值,不过这种情况很少发生),就会报出错误。接下来是对需要等待的程序进行一些列的处理。先是给这个程序分配锁,对它的程序空间和内部变量进行封锁。同时把这个加锁后的程序放进双端队列(deque)‘等待者们’中。

好像wait()方法的功能到此就结束了。但是注意到下面还有try函数块,旁边一行注释写着‘restore  state  no matter  what’然后又举了一个KeyboardInterrupt的异常情况。意思是当出现了例如键盘输入ctrl+C这类操作的时候,程序如何退出阻塞。如果在调用wait方法的时候没有传入timeout参数,那么,等待者程序就会重新获取锁。如果有timeout参数,就会根据参数来确定退出阻塞的时间。这就是为什么我们有时在输入ctrl+C强行退出阻塞的时候,程序会等待一会儿才给出退出程序的提示的原因。

 

 3. notify()方法

接下来这个notify()方法在Condition类中也是非常的重要(queue模块内部也调用了这个函数)

notify()方法内部实现:

notify直接翻译过来就是‘提示’的意思。那么为什么Condition对象需要‘提示’呢?阅读源码下来,其真正的功能不是提示,而是锁的释放,并且在释放了指定数量的waiters之后,顺便将他们从‘等待者们’队列中删除。如果直接理解为提示,就会很难理解了。但这是老外在定义函数时的写法,本人的理解是,有点像给阻塞的程序发出信号(提示),停止阻塞(释放锁),这么理解应该也算勉强解释得过去吧。

 

Condition内部另外还有一个notify_all()方法,这个方法对‘等待者们’队列中的所有的程序都发出‘提示’,释放锁,而没有像notify中那样有数量n的限制。

源码:

 

那么总结上面的Condititon内部的方法实现,可以看出,Condition类是为了实现一种状态的‘保存’,即在多线程编程的情况下,由于线程间共享空间而容易引发错误,往往需要让一些线程先执行,而后面的线程等待(阻塞)。那么如果这些程序需要阻塞等待,就会调用Condition类实例对象的wait方法,当结束等待的信号发出时,就会调用Condition的notify方法对队列中的程序进行释放锁操作。

 

二、关于SegmaphoreBoundedSegmaphore

如果在主机执行IO密集型任务的时候再执行这种短时间内完成大量任务(多线程)的程序时,计算机就有很大可能会宕机。

这时候就可以为这段程序添加一个计数器(counter)功能,来限制一个时间点内的线程数量。当每次进行IO操作时,都需要向segmaphore请求资源(锁),如果没有请求到,就阻塞等待,请求成功才就像执行任务。

 

那么segmaphore的内部实现是怎样的呢?实质上segmaphore也是锁,其内部也是通过Lock和Condition实现的。Lock是单锁,而segmaphore是可以自己定义的多锁。在初始化segmaphore时,需要传入参数counter。当线程向segmaphore请求资源(锁)时,内部的counter会自动减1。当释放资源(锁)的时,counter就会自动加1。

segmaphore主要有两个方法,acquire()和release()方法。

1. acquire()方法

官方的定义:

def acquire(self, blocking=True, timeout=None):

当内部的counter(源码实际上是用value变量保存)等于0的时候,其他线程acquire会阻塞。这个时候,之前向segmaphore发出请求并获得锁的线程,它们如果同时执行完任务并希望释放锁时,那么锁的释放是随机的。任何一个完成任务的线程都会释放锁,这个顺序跟线程向请求的时间和任务完成的时间是没有任何关系的。

参数的解析:

1)blocking:默认为True,当线程请求不到资源的时候,会阻塞等待。如果设置为False,则线程请求不到资源时不会阻塞。

2)timeout:如果设置blocking = True,即默认值时,经过timeout时间会退出阻塞。

 

2. release()方法

这个方法与Lock的release方法很像,具体可以看看我之前写的关于锁的一篇文章。

链接:python同步原语--线程锁 

源码:

解析:

当一个实例请求释放锁的时候,segmaphore内部的_value会自动加1,同时调用notify方法,将被锁住的线程‘唤醒’。

 

 

三、关于Event类

阅读源码知道,Event是也基于Condition和Lock实现的

 

1. set()方法

在 python--线程同步原语 这篇文章我曾经写过一个案例,在进程中调用一次event.set()函数就可以一次性通知(释放)所有阻塞的等待的锁。其内部实现的原理在这里,最关键的一个方法是notify_all()。

在调用set()方法的时候,方法内部会将_flags设置为True,即等待的事件会退出阻塞。

 

2. clear()方法

clear()方法不同作太多解析了,就是内部的_flags重新设置为False

 

3. wait()方法

wait()方法的定义:

def wait(self, timeout=None):

内部实现:

原理还是很简单的,实际上Event的wait()方法正是调用了Condition中的实例方法wait()。调用wait()方法的时候可以传入参数timeout(超时时间),作为Event事件自动退出阻塞的时间界限。

 

--结束END--

本文标题: python线程同步原语--源码阅读

本文链接: https://lsjlt.com/news/180270.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • python线程同步原语--源码阅读
    前面两篇文章,写了python线程同步原语的基本应用。下面这篇文章主要是通过阅读源码来了解这几个类的内部原理和是怎么协同一起工作来实现python多线程的。 相关文章链接:python同步原语--线程锁                  ...
    99+
    2023-01-30
    线程 源码 python
  • python同步原语--线程锁
    多线程锁是python多种同步原语中的其中一种。首先解析一下什么是同步原语,python因为GIL(全局解析锁)的缘故,并没有真正的多线性。另外python的多线程存在一个问题,在多线程编程时,会出现线程同时调用共同的存储空间而导致错误的...
    99+
    2023-01-30
    线程 python
  • Android源码在线阅读
    ⭐博客同步更新在blogs-index ⭐推荐在github上阅读 推荐几个我在用的Android源码在线阅读网站,方便随时随地学习Android代码。 AOSPXRef 代码比较齐全,...
    99+
    2023-09-02
    android
  • Android线程池源码阅读记录介绍
    今天面试被问到线程池如何复用线程的?当场就懵掉了...于是面试完毕就赶紧打开源码看了看,在此记录下: 我们都知道线程池的用法,一般就是先new一个ThreadPoolExecutor...
    99+
    2024-04-02
  • python json-rpc 规范源码阅读
    目录json-rpc 源码阅读JSON-RPC规范jsonrpcclient的实现jsonrpcserver的实现小结小技巧json-rpc 源码阅读 JSON-RPC是一个无状态且...
    99+
    2024-04-02
  • Java终止线程实例和stop()方法源码阅读
    了解线程概念线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。线程特点拥有状态,表示线程的状态,同一时刻中,JVM中的某个线程只有一种状态;·NEW尚未启动的线程(程序运行开始至今一次未启动的线程)·RUNNAB...
    99+
    2023-05-30
  • spring源码阅读--@Transactional实现原理讲解
    目录@Transactional注解简介spring中声明式事务实现原理猜想@Transactional作用动态代理逻辑实现TransactionInterceptor–最终事务管理...
    99+
    2024-04-02
  • spring源码阅读--aop实现原理讲解
    目录aop实现原理简介代理实现的处理器(BeanPostProcessor)代理实现的源头–AnnotationAwareAspectJAutoProxyCreatorAnnotat...
    99+
    2024-04-02
  • 教你阅读Python开源项目代码
    作者:董伟明 链接:https://zhuanlan.zhihu.com/p/22275595 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。注:本专栏文章未经允许请勿转载。 知乎上有不少人问和关注阅读开...
    99+
    2023-01-31
    教你 开源 代码
  • Python线程同步
    from random import randint import threading from time import ctime, sleep data = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h...
    99+
    2023-01-31
    线程 Python
  • Java CountDownLatch线程同步源码硬核解析
    目录场景CountDownLatch代码demo场景 有时间在主线程中开启了多线程后,主线程需要等所有线程执行完毕才能return,这个时候就需要在return前拦一下,直到所有线程...
    99+
    2023-01-28
    Java CountDownLatch Java线程同步 Java CountDownLatch线程同步
  • 程序员是怎么阅读源码的
    本篇内容介绍了“程序员是怎么阅读源码的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!React:React 架构的演变 - 从同步到异步Re...
    99+
    2023-06-15
  • 完结篇 | TiDB Binlog 源码阅读系列文章 (九)同步数据到下游
    上篇文章介绍了用于将 binlog 同步到 MySQL / TiDB 的 Loader package,本文往回退一步,介绍 Drainer 同步到不同下游的机制。 TiDB Binlog(github.com/pingcap/tidb...
    99+
    2022-04-28
    完结篇 | TiDB Binlog 源码阅读系列文章 (九)同步数据到下游
  • Python的线程之线程同步
    目录线程同步threading.Lock获取同步锁总结在多线程程序中,它们互相独立打印的时间却是错乱的! 如下图,明明t-0 > t-1 > t-2 (按照线程创建时间早...
    99+
    2024-04-02
  • ReentrantLock从源码解析Java多线程同步学习
    目录前言管程管程模型MESA模型主要特点AQS共享变量资源访问方式主要方法队列node节点等待状态ReentrantLock源码分析实例化ReentrantLock加锁A线程加锁成功...
    99+
    2023-05-16
    Java多线程ReentrantLock Java ReentrantLock
  • Java线程同步Lock同步锁代码示例
    java线程同步原理java会为每个object对象分配一个monitor,当某个对象的同步方法(synchronizedmethods)被多个线程调用时,该对象的monitor将负责处理这些访问的并发独占要求。当一个线程调用一个对象的同步...
    99+
    2023-05-30
    java 线程同步 lock
  • Eureka源码阅读之环境搭建及工程结构
    目录1. 源码阅读环境搭建1.1 源码下载:2. 工程结构速览3. 调试须知1. 源码阅读环境搭建 ide:IntelliJ IDEA 2020.1包管理:gradleeureka版...
    99+
    2022-11-13
    Eureka 环境搭建结构调试 Eureka环境搭建
  • Python 中的进程、线程、协程、同步
    进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生?在刚刚结束的 PyCon2014 上海站,来自七牛云存储的 Python 高级工程师许智翔带来了关于 Python 的分享《Pyt...
    99+
    2023-01-31
    线程 进程 Python
  • 教你使用IDEA搭建spring源码阅读环境的详细步骤
    目录第一步、准备gradle环境第二步、下载spring源码第一步、准备gradle环境 1、去官网下载gradle https://gradle.org/releases/ 2、...
    99+
    2024-04-02
  • python多线程同步售票系统
    目录1、分析过程2、准备过程3、实现过程解决问题场景:假如剩余1000张电影票需要售卖,同时有10家电影App来售卖这1000张电影票。主要的逻辑实现过程是什么,要求使用python...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作