Seqlock

Seqlock是最可扩展的锁形式,如果有大量读取器,则很有用。

读者不需要写任何内存来处理这种“锁”。也许根本不应该谈论获得锁。

读者比较关键部分前后的计数器。

如果计数器在关键部分没有改变,则没有编写者处于活动状态,并且关键部分产生的结果有效。

如果已更改,则将丢弃关键部分的结果,然后再次运行。

ps: 这个思想也非常简单。读的时候不去阻塞写,如果发生了写那就重新加载一遍读取的内容即可

seqlock包含一个自旋锁,用于在作者之间进行互斥。

一旦获得锁定,写入器就会使计数器递增,从而得出奇数计数值。

读者知道,如果作者遇到一个奇数值,然后重新运行该关键部分,则该作者将位于关键部分。

写入器在解锁时再次增加计数器,使其变为偶数。

锁获取需要两个原子信号操作。

一个获取自旋锁,另一个获取计数器。

写解锁需要一个信号量操作来增加计数器,并需要一个存储来解锁自旋锁。

这意味着seqlock编写器的效率不如常规自旋锁或rwlock。

  • Drawing 7 SeqLock

SeqLock

读者可以通过重复执行关键部分来推迟执行。

如果作家很少,这很好。在无竞争的情况下,锁所涉及的全部是两个内存读取操作和两个内存屏障。

如果在执行读者关键部分时有作家正在活动或曾经活跃,则我们知道结果无效,我们需要重复该关键部分。

seqlock主要用于Linux中的时间检索。

对于Itanium,我能够避免在读取时间信息时钟期间进行任何写操作,从而使时钟访问变得高度可扩展。

所有处理器都可以维护自己的包含相关信息的缓存行副本。

seqlocks的问题在于,由于关键部分必须是可重复的,因此读取器除了读取值之外,实际上无法在关键部分中执行任何操作

读取的关键部分可能与写入的关键部分竞争。因此,对于写入者或读取者执行指针结构的更新,分配存储器等是有问题的。

从性能角度来看,这是一种理想的锁类型,因为读者永远不需要独占缓存行。

理想情况下,编写者获得一个专有的高速缓存行,其中包含自旋锁和计数器以及偶尔管理的数据,并更新信息。

参考资料

linux 锁实现