JDK 伪共享解决方案

关于AtomicReference

AtomicReference是由JAVA5引入的,用于对一个对象引用进行原子操作,我们可以看到AtomicReference的实现是用CAS技术对引用进行指令级别的原子修改,

然后再利用volatile带来的内存屏障特性, 保证引用的修改对其他线程立即可见。这里提一点,由volatile修饰的变量在写之后会插入一个store屏障,在读之前插入

一个load屏障。store屏障保证写操作被后面的线程立即可见。load屏障保证所有的读操作之前的写立即生效。然而AtomicReference并没有避免缓存行带来的缓

存命中率问题。一个AtomicReference对象包括一个volatile的对象引用,即这个对象在32位操作系统中占4个字节,在64位操作系统中占8个字节。虽然多个线程

对同一个AtomicReference对象操作没有并发问题,但是当多个线程对多个AtomicReference操作的时候就有可能有缓存命中率问题。借着上文中的模型我们假设

两个AtomicReference变量A和B位于同一内存相邻区域,当在核心1执行的线程对A变量操作的时候CPU会将A变量读入核心1的缓存区域,同时捎带把B变量读入缓

存区域,此时和A变量位于同一缓存行。核心2执行的另外一个线程同时对B进行操作,这个时候该缓存行已经失效,会发生一次读内存操作。

缓存行填充

Exchanger类是JAVA5提供的用于多线程之间交换数据的工具类,我们看看Exchanger的内部类Slot的实现:

private static final class Slot extends AtomicReference<Object> {
        // Improve likelihood of isolation on <= 64 byte cache lines
        long q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe;
    }

Slot只是简单的继承了AtomicReference类,并声明了15个long类型的变量。如果不懂CacheLine的话不会明白这段无用变量的意义,这里声明了15个long类型的变量,

一个long类型为8个字节,加上上面的引用在64位操作系统环境下为128字节,32位操作系统环境下的124字节也没问题,因为两个Slot类型变量不可能位于同一缓存行,

这也就解决了多核CPU环境下的缓存航失效问题。

Disruptor的伪共享解决方案 http://www.cnblogs.com/yuyutianxia/p/6365959.html

EXchanger 解析: http://lixuanbin.iteye.com/blog/2166772

原文地址:https://www.cnblogs.com/yuyutianxia/p/7132197.html