LockFreeHashMap:无阻塞代码技巧
10年前,cliff click博士就为关联数据结构ConcurrentHashMap给出了一个采用open Address的无阻塞实现(NonBlockingHashMap)。其中为了减少线程之间执行顺序的依赖而采用的算法充满技巧性。这个算法宣称是无锁,几乎可以保证任何时候停止某个特定线程都不会导致整体进程的停止(极端情况下,这一点还是会阻塞整个进程的)。
10年前,cliff click博士就为关联数据结构ConcurrentHashMap给出了一个采用open Address的无阻塞实现(NonBlockingHashMap)。其中为了减少线程之间执行顺序的依赖而采用的算法充满技巧性。这个算法宣称是无锁,几乎可以保证任何时候停止某个特定线程都不会导致整体进程的停止(极端情况下,这一点还是会阻塞整个进程的)。
JVM中有这样一段注释:
[code lang=”java”]
// The base-class, PlatformEvent, is platform-specific while the ParkEvent is
// platform-independent. PlatformEvent provides park(), unpark(), etc., and
// is abstract — that is, a PlatformEvent should never be instantiated except
// as part of a ParkEvent.
// Equivalently we could have defined a platform-independent base-class that
// exported Allocate(), Release(), etc. The platform-specific class would extend
// that base-class, adding park(), unpark(), etc.
//
// A word of caution: The JVM uses 2 very similar constructs:
// 1. ParkEvent are used for Java-level "monitor" synchronization.
// 2. Parkers are used by JSR166-JUC park-unpark.
//
// We’ll want to eventually merge these redundant facilities and use ParkEvent.
[/code]
StampedLock作为JAVA8中出现的新型锁,很可能在大多数场景都可以替代ReentrantReadWriteLock。它对于读/写都提供了四个接口(换成write为写锁):
这几个方法对应的语义为:
一个因中断或者超时的调用可能会引起数据丢失和CPU爆满。
前几天读LinkedTransferQueue(以下简称ltq)的源码,想加深下对松弛型双重队列的理解,无意中发现了这个问题:),经过仔细检查后确认了这是个bug,存在于JDK1.7.0_40和刚发布的JDK8中,去google和oracle官方似乎也没有搜索到这个问题。
重现bug:先来重现下这个bug,由于对并发线程的执行顺序预先不能做任何假设,所以很可能根本就不存在所谓的重现错误的“测试用例”,或者说这个测试用例应该是某种“执行顺序”。所以我一开始的做法是copy了一份ltq的源码,通过某个地方加自旋…但是这种方法毕竟要修改源码,后来我发现直接debug进源码就可以轻易重现bug了。 阅读全文