如何以无锁方式自动更新 2 个对象?
Posted
技术标签:
【中文标题】如何以无锁方式自动更新 2 个对象?【英文标题】:How to update 2 objects atomically in a lock-free manner? 【发布时间】:2015-04-26 13:27:14 【问题描述】:我正在研究通过多个对象实现基于哈希码的原子锁定的类。主要目的是在所有需要的锁都可用时立即解除等待者线程,从而减少总体等待时间。
它的lockAndGet(List objects)
返回一个涉及所有列出对象的“复合锁”。调用者完成工作后,它会调用unlock()
。
主要组件有:1)普通锁表--int[]
数组显示现在持有哪些锁; 2) 服务员线程的双端队列。
算法很简单:
-
当一个线程调用
lockAndGet()
时,它被标记为停放,然后新的waiter object包含这个线程,状态为LOCKED
被创建并添加到队列的尾部,之后makeRound()
方法被调用;
makeRound()
从头部开始遍历双端队列,试图找到哪些服务员可以获得他们的锁。当找到一个这样的服务员时,锁表被更新,服务员状态更改为UNLOCKED
并从双端队列中删除,服务员的线程被取消驻留。遍历后,如果当前线程被标记为停放,则停放;
当在某个复合锁上调用unlock()
时,锁表状态会更新并调用makeRound()
。
这里,为了避免竞争条件,锁表状态的更新必须与等待者状态的更新一起原子地执行。现在,它是通过普通独占Lock
上的同步来实现的,并且效果很好,但是我想使用CAS操作以free-lock方式实现类似的机制,使waiter queue无锁。第 1 步很简单,但第 2 步有问题。
由于 Java 不支持 DCAS,有谁知道怎么做 可以实现队列节点的更新(服务员状态的改变和删除标记)原子地更新其他对象(锁表),只使用CAS?我不要求提供代码,只是提供一些可能有所帮助的提示或方法。
【问题讨论】:
您是否真的有性能问题促使您尝试寻找无锁算法?这些很难做到正确。否则有很多解决方案(信号量、锁存器、条件等) @fge 在我目前的方法中,我使用锁和信号量的组合,它工作得非常正确且非常快。但我无法判断只有一种基于锁的实现会更好:没有可比性!无锁并不容易,对吧。我犹豫在 SO 中发布简单的问题。 执行多个值的同步更新基本上有三种方法:1)使用锁,2)使用“安全序列”(很难做到正确,假设甚至有解决方案) , 3) 使用某种机器设备(例如禁用调度程序)。但请注意,“锁”有多种形式——计数器、信号量、操作系统定义的锁等。 【参考方案1】:您可以尝试使用可用的 CAS 来实现多字 CAS,但这取决于您愿意为实现这一目标付出多少性能损失。
你可以看看哈里斯的http://www.cl.cam.ac.uk/research/srg/netos/papers/2002-casn.pdf
【讨论】:
谢谢,我去看看以上是关于如何以无锁方式自动更新 2 个对象?的主要内容,如果未能解决你的问题,请参考以下文章
为啥标准库不以无锁方式为 8 字节以下的结构实现 std::atomic?