java无锁无锁hashmap原理与实现详解原理与实现详解
本文主要介绍了java无锁hashmap原理与实现,大家参考使用吧
java多线程环境中应用HashMap,主要有以下几种选择:使用线程安全的java.util.Hashtable作为替代使用
java.util.Collections.synchronizedMap方法,将已有的HashMap对象包装为线程安全的。使用
java.util.concurrent.ConcurrentHashMap类作为替代,它具有非常好的性能。
而以上几种方法在实现的具体细节上,都或多或少地用到了互斥锁。互斥锁会造成线程阻塞,降低运行效率,并有可能产生死
锁、优先级翻转等一系列问题。
CAS(Compare And Swap)是一种底层硬件提供的功能,它可以将判断并更改一个值的操作原子化。
Java中的原子操作中的原子操作
在java.util.concurrent.atomic包中,Java为我们提供了很多方便的原子类型,它们底层完全基于CAS操作。
例如我们希望实现一个全局公用的计数器,那么可以:
复制代码 代码如下:
privateAtomicInteger counter =newAtomicInteger(3);
publicvoidaddCounter() {
for(;;) {
intoldValue = counter.get();
intnewValue = oldValue +1;
if(counter.compareAndSet(oldValue, newValue))
return;
}
}
其中,compareAndSet方法会检查counter现有的值是否为oldValue,如果是,则将其设置为新值newValue,操作成功并返回
true;否则操作失败并返回false。
当计算counter新值时,若其他线程将counter的值改变,compareAndSwap就会失败。此时我们只需在外面加一层循环,不断
尝试这个过程,那么最终一定会成功将counter值+1。(其实AtomicInteger已经为常用的+1/-1操作定义了 incrementAndGet与
decrementAndGet方法,以后我们只需简单调用它即可)
除了AtomicInteger外,java.util.concurrent.atomic包还提供了AtomicReference和AtomicReferenceArray类型,它们分别代表
原子性的引用和原子性的引用数组(引用的数组)。
无锁链表的实现无锁链表的实现
在实现无锁HashMap之前,让我们先来看一下比较简单的无锁链表的实现方法。
以插入操作为例:
首先我们需要找到待插入位置前面的节点A和后面的节点B。
然后新建一个节点C,并使其next指针指向节点B。(见图1)
最后使节点A的next指针指向节点C。(见图2)