chronyc 手动同步某节点(chrony查看同步状态)

chronyc 手动同步某节点(chrony查看同步状态)线程同步 概念 Event 练习 总结 wait 的使用 定时器 Timer 延迟执行 总结 Lock 锁的基本使用 练习 加锁 解锁 加锁 解锁常用语句 锁的应用场景 非阻塞锁使用 可重入锁 RLock 可重入锁总结 Condition Condition 基本使用 Condition 总结 semaphore 信号量 release 方法超界问题 BoundedSemap 类 应用举例

大家好,我是讯享网,很高兴认识大家。



线程同步

  • 概念
  • Event
  • 练习
  • 总结
  • wait的使用
  • 定时器 Timer/延迟执行
  • 总结
  • Lock
  • 锁的基本使用
  • 练习
  • 加锁、解锁
  • 加锁、解锁常用语句:
  • 锁的应用场景
  • 非阻塞锁使用
  • 可重入锁RLock
  • 可重入锁总结
  • Condition
  • Condition基本使用
  • Condition总结
  • semaphore 信号量
  • release方法超界问题
  • BoundedSemaphore类
  • 应用举例
  • 问题
  • 1、边界问题分析
  • 2、正常使用分析
  • 信号量和锁
  • 线程同步,线程间协同,通过某种技术,让一个线程访问某些数据时,其他线程不能访问这些数据,直到该线程完成对数据的操作

Event事件,是线程间通信机制中最简单的实现,使用一个内部的标记flag,通过flag的True或False的变化来进行操作

练习

老板雇佣了一个工人,让他生产杯子,老板一直等着这个工人,直到生产了10个杯子

总结

  • 使用同一个Event对象的标记flag
  • 谁wait就是等到flag变为True,或等到超时返回False。不限制等待的个数

wait的使用

定时器 Timer/延迟执行

继承自,这个类用来定义延迟多久后执行一个函数

start方法执行之后,Timer对象会处于等待状态,等待了interval秒之后,开始执行function函数的

  • 上例代码工作线程早就启动了,只不过是在工作线程中延时了4秒才执行了worker函数

Timer是线程Thread的子类,Timer实例内部提供了一个finished属性,该属性是Event对象。cancel方法,本质上是在worker函数执行前对finished属性set方法操作,从而跳过了worker函数执行,达到了取消的效果

总结
  • Timer是线程Thread的子类,就是线程类,具有线程的能力和特征
  • 它的实例是能够延时执行目标函数的线程,在真正执行目标函数之前,都可以cancel它
  • cancel方法本质使用Event类实现。这并不是说,线程提供了取消的方法
  • 锁,一旦线程获得锁,其它试图获取锁的线程将被阻塞
  • 锁:凡是存在共享资源争抢的地方都可以使用锁,从而保证只有一个使用者可以完全使用这个资源

锁的基本使用

  • 第三个print永久阻塞
  • 不阻塞,获取不到返回Fasle

非阻塞时不要设置timeout值,否则会抛ValueError错误


讯享网

  • 执行结果

上例可以看出不管在哪一个线程中,只要对一个已经上锁的锁阻塞请求,该线程就会阻塞。

练习

订单要求生产1000个杯子,组织10个工人生产。请忽略老板,关注工人生成杯子

  • 上例中共有三处可以释放锁。只有第二出释放锁的位置正确
  • 假设位置1的合适,分析如下:
    有一个时刻,在某一个线程中正好是999,,释放锁,正好线程被打断。另一个线程判断发现也是999,,可能线程被打断。可能另外一个线程也判断是999,flag也设置为True。这三个线程只要继续执行到,一定会导致cups的长度超过1000的。

  • 假设位置2的合适,分析如下:
    在某一个时刻,正好是999,,其它线程试图访问这段代码的线程都阻塞获取不到锁,直到当前线程安全的增加了一个数据,然后释放锁。其它线程有一个抢到锁,但发现已经1000了,只好break打印退出。再其它线程都一样,发现已经1000了,都退出了。
    所以位置2 释放锁 是正确的。
    但是我们发现锁保证了数据完整性,但是性能下降很多。







  • 上例中位置3,是为了保证位置2的方法被执行,否则,就出现了死锁,得到锁的永远没有释放锁

加锁、解锁

  • 一般来说,加锁就需要解锁,但是加锁后解锁前,还要有一些代码执行,就有可能抛异常,一旦出现异常,锁是无法释放,但是当前线程可能因为这个异常被终止了,这也产生了死锁。
加锁、解锁常用语句:
  1. 使用语句保证锁的释放
  2. 上下文管理,锁对象支持上下文管理
  • 计数器类,可以加,可以减

锁的应用场景

  • 少用锁,必要时用锁。使用了锁,多线程访问被锁的资源时,就成了串行,要么排队执行,要么争抢执行
  • 举例,高速公路上车并行跑,可是到了省界只开放了一个收费口,过了这个口,车辆依然可以在多车道上一起跑。过收费口的时候,如果排队一辆辆过,加不加锁一样效率相当,但是一旦出现争抢,就必须加锁一辆辆过。注意,不管加不加锁,只要是一辆辆过,效率就下降了
  • 加锁时间越短越好,不需要就立即释放锁
  • 一定要避免死锁

非阻塞锁使用

  • 可重入锁,是线程相关的锁。
  • 线程A获得可重复锁,并可以多次成功获取,不会阻塞。最后要在线程A中做和acquire次数相同的release
  • 执行结果

可重入锁总结

  • 与线程相关,可在一个线程中获取锁,并可继续在同一线程中不阻塞多次获取锁
  • 当锁未释放完,其它线程获取锁就会阻塞,直到当前持有锁的线程释放完锁
  • 锁都应该使用完后释放。可重入锁也是锁,应该acquire多少次,就release多少次
  • 构造方法 ,可以传入一个Lock或RLock对象,默认是RLock

Condition基本使用

Condition用于生产者、消费者模型,为了解决生产者消费者速度匹配问题

  • 下例只是为了演示,不考虑线程安全问题
  • 执行结果

这个例子,可以看到实现了消息的 一对多 ,这其实就是 广播模式
注:上例中,程序本身不是线程安全的,程序逻辑有很多瑕疵,但是可以很好的帮助理解Condition的使用和生产者消费者模型

Condition总结

  • 使用方式
    使用Condition,必须先acquire,用完了要release,因为内部使用了锁,默认使用RLock锁,最好的方式是使用with上下文
    消费者wait,等待通知
    生产者生产好消息,对消费者发通知,可以使用notify或者notify_all方法







  • 和Lock很像,信号量对象内部维护一个倒计数器,每一次acquire都会减1,当acquire方法发现计数为0就阻塞请求的线程,直到其它线程对信号量release后,计数大于0,恢复阻塞的线程
  • 计数器永远不会低于0,因为acquire的时候,发现是0,都会被阻塞

release方法超界问题

  • 假设如果还没有acquire信号量,就release,会怎么样?

从上例输出结果可以看出,竟然内置计数器达到了4,这样实际上超出我们的最大值,需要解决这个问题

有界的信号量,不允许使用release超出初始值的范围,否则,抛出ValueError异常

  • 连接池
    因为资源有限,且开启一个连接成本高,所以,使用连接池

  • 一个简单的连接池
    连接池应该有容量(总数),有一个工厂方法可以获取连接,能够把不用的连接返回,供其他调用者使用

真正的连接池的实现比上面的例子要复杂的多,这里只是简单的一个功能的实现

  • 本例中,get_conn()方法在多线程的时候有线程安全问题
    假设池中正好有一个连接,有可能多个线程判断池的长度是大于0的,当一个线程拿走了连接对象,其他线程再来pop就会抛异常的。如何解决?
    1、加锁,在读写的地方加锁
    2、使用信号量Semaphore







使用信号量对上例进行修改

  • 注意:这个连接池的例子不能用到生成环境,只是为了说明信号量使用的例子,连接池还有很多未完成功能

self.conns.append(conn) 这一句有哪些问题考虑?

1、边界问题分析

  • 假设一种极端情况,计数器还差1就归还满了,有三个线程A、B、C都执行了第一句,都没有来得及release,这时候轮到线程A release,正常的release,然后轮到线程C先release,一定出问题,超界了,直接抛异常
  • 因此信号量,可以保证,一定不能多归还
  • 如果归还了同一个连接多次怎么办,重复很容易判断
    这个程序还不能判断这些连接是不是原来自己创建的,这不是生成环境用的代码,只是简单演示

2、正常使用分析

  • 正常使用信号量,都会先获取信号量,然后用完归还
  • 创建很多线程,都去获取信号量,没有获得信号量的线程都阻塞。能归还的线程都是前面获取到信号量的线程,其他没有获得线程都阻塞着。非阻塞的线程append后才release,这时候等待的线程被唤醒,才能pop,也就是没有获取信号量就不能pop,这是安全的
  • 经过上面的分析,信号量比计算列表长度好,线程安全

信号量和锁

  • 信号量,可以多个线程访问共享资源,但这个共享资源数量有限
  • 锁,可以看做特殊的信号量,即信号量计数器初值为1。只允许同一个时间一个线程独占资源

小讯
上一篇 2025-04-20 17:01
下一篇 2025-05-15 07:15

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/161674.html