当前位置:网站首页 > 时间管理与高效工作 > 正文

条件变量 互斥锁(互斥锁和条件变量机制的工作流程)



postgresql 的架构是基于多进程的,进程之间往往存在着数据共享,比如缓存读写。这时 postgresql 需要提高一种锁机制来支持并发访问,但是 linux 只实现了线程间的读写锁,所以 postgresql 自己实现进程间的读写锁,它主要利用了信号量和自旋锁来实现。

每个进程都对应一个独立  实例,它包含了多个成员,下面只列出与锁相关的

 实例存储在进程共享内存里,在创建进程时会被初始化。这里需要提醒下,信号量 sem 的初始值为0,属于无名信号量。

结构体表示读写锁,结构如下:

需要介绍下 state 字段的标记位

加锁原理

函数负责整个加过程,这里将过程分为下面四步:

从上面可以看出来,这里采用的是非公平锁机制,也就是谁的速度快,谁就能获取到锁,没有先来先获取的顺序。

尝试通过 CAS 操作,设置或标记位。来获取锁。使用到的 CAS 操作函数如下:

当尝试获取读锁时,只需要检查标记位。如果为零,就认为成功获取。

对于队列的操作,都需要使用自旋锁来设置 标记位,才有权利操作队列。当设置成功后,会将自身添加到等待列表,然后更新自身进程对应实例的  和  成员,最后释放锁,清除标记位。

当加入到队列后,还需要更新标记位,表示有进程在等待。

postgresql 是多进程架构的,进程之间使用信号量来同步。当进程获取锁失败时,会将自身添加到等待队列里,然后通过信号量进行阻塞,直到被别的进程唤醒。对于 postgresql 的每个进程都有一个信号量,由实例的 sem 成员表示。sem 信号量的初始值为0,它的数值代表着满足的条件数。

因为这个 sem 信号量会有多个用途,所以每次唤醒操作,并不一定是期望的条件发生,所以进程在被唤醒之后,需要一次条件检查。如果是因为其他条件唤醒,还需要记录被唤醒次数,在事后需要将执行相应次数的唤醒操作。

假设下面有一个进程A对应信号量A,它会被用于两个方面,条件A和条件B。

进程A正在阻塞条件A,此时进程B因为条件B唤醒了进程A。但进程A发现并不是期望的条件所唤醒的,所以它会继续阻塞,直到满足条件A被唤醒,最后进程A还会执行一次唤醒操作。

当获取到锁之后,如果自身在等待队列中,需要将其删除掉。如果之后队列为空,需要清除标记位,当然这些操作都需要获取锁。

下面展示了的源码,描述了整个加锁过程

释放锁

函数负责释放锁,定义如下:

释放锁分为下列步骤:

下面列举了两种情况来阐述锁释放的原理:

在取出进程之后,会清除标记位。如果检查到队列为空,还会清除标记位。

lwlock 在 postgresql 中使用的场景非常多,为了更好管理这些 lwlock,postgresql 按照用途将它们分类,大体分为三个部分:

到此这篇条件变量 互斥锁(互斥锁和条件变量机制的工作流程)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 我的世界暂停指令是什么(我的世界暂停时间的指令)2026-01-28 20:54:08
  • keil破解时间2020年到期(keil5破解到期)2026-01-28 20:54:08
  • 神兽刷新时间指令(查看神兽刷新时间指令)2026-01-28 20:54:08
  • 我的世界暂停时间指令(我的世界暂停时间指令网易)2026-01-28 20:54:08
  • 我的世界设置时间指令黎明(我的世界指令调时间午夜)2026-01-28 20:54:08
  • 如何查看神兽刷新时间(如何查看神兽刷新时间表)2026-01-28 20:54:08
  • ad9850原理图(ad9850工作原理)2026-01-28 20:54:08
  • 我的世界神兽刷新时间指令(我的世界神兽刷新指令时间)2026-01-28 20:54:08
  • 查一次刷神兽时间的指令(查一次刷神兽时间的指令是什么)2026-01-28 20:54:08
  • 文件管理工作内容(文件管理工作职责)2026-01-28 20:54:08
  • 全屏图片