zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    PHP之十六个魔术方法详解
    PHP之十六个魔术方法详解
    让Docker容器使用静态独立的外部IP(便于集群组建)
    桥接和nat模式区别
    使用 GitHub / GitLab 的 Webhooks 进行网站自动化部署
    docker gitlab
    docker gitlab安装
    docker ui管理工具
    docker 批量删除容器
    Scrapy设置代理
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/7132197.html
Copyright © 2011-2022 走看看