当前位置:网站首页 > R语言数据分析 > 正文

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



线程同步

  • 概念
  • 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。只允许同一个时间一个线程独占资源
到此这篇chronyc 手动同步某节点(chrony查看同步状态)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • docker-ce版本(docker版本号有哪些)2025-08-21 16:27:05
  • treesize free怎么切换中文(treesizefree 安卓)2025-08-21 16:27:05
  • airplus02是什么牌子耳机(airplusair耳机是什么牌子?)2025-08-21 16:27:05
  • 启动docker(termux启动docker)2025-08-21 16:27:05
  • termux启动ubuntu命令(ubuntu启动terminal)2025-08-21 16:27:05
  • arg怎么读?(trousers怎么读)2025-08-21 16:27:05
  • swagger3使用(swagger2使用)2025-08-21 16:27:05
  • persistent_dhclient作用(/sbin/dhclient)2025-08-21 16:27:05
  • resnet网络解决了什么问题(resnet网络特点)2025-08-21 16:27:05
  • 搭建chrony服务器(服务器搭建windows)2025-08-21 16:27:05
  • 全屏图片