• 姜戈
    2019-09-09
    课后问题:
    对比了Sequence与AtomicLong源码,在于CAS之前,Disruptor直接取原有值,做CAS操作;而AtomicLong使用了getLongVolatile获值。
    两者value都用了Volatile来修饰,这点是共同的;但在于获值时,AtomicLong又再次使用volatile(getLongVolatile), 由于Volatile会在内存中强行刷新此值,相比这样就会增加一次性能的消耗,另外还有Spinlock(自旋锁),这两点都会带来性能消耗。
    为什么Disruptor可以这样做,免掉getLongVolatile操作,我猜想应该是缓存行的填充,避免了伪共享(False Sharing)的问题,线程对value值的修改,不会出现不同线程同时修改同一缓存行不同变量的问题,所以不需要再次强行刷内存的步骤。

    请老师指正!!!

     /** Sequence关于取值是直接Get(), 查看内部方法直接返回value
         *
         * Atomically add the supplied value.
         *
         * @param increment The value to add to the sequence.
         * @return The value after the increment.
         */
        public long addAndGet(final long increment)
        {
            long currentValue;
            long newValue;

            do
            {
                currentValue = get();
                newValue = currentValue + increment;
            }
            while (!compareAndSet(currentValue, newValue));

            return newValue;
        }

    /** AtomicLong关于取值时使用getLongVolatile,查看其源码,增加了Volatile和自旋锁
         *
         * getAndAddLong
         *
    */
    public final long getAndAddLong(Object var1, long var2, long var4) {
            long var6;
            do {
                var6 = this.getLongVolatile(var1, var2);
            } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

            return var6;
        }

    /** getLongVolatile源码(C++)
       *
       * 1. volatile, 刷新内存
       * 2.Spinlock, 自旋锁
       */
    jlong
    sun::misc::Unsafe::getLongVolatile (jobject obj, jlong offset)
    {
      volatile jlong *addr = (jlong *) ((char *) obj + offset);
      spinlock lock;
      return *addr;
    }
    展开

    作者回复: 抱歉,不过你的 AtomicLong 部分的代码时从哪里看到的?似乎和open jdk里面的源码完全不一样。

    Sequence主要是做了Cache Line Padding,来解决False Sharing的问题,和AtomicLong比较,避免Cache里面的数据被反复交换到内存里面去。

    “ In fact the only real difference between the 2 is that the Sequence contains additional functionality to prevent false sharing between Sequences and other values.”

     1
     8
  • 活的潇洒
    2019-09-15
    极客时间买了13个专栏,终于完成了一个专栏的所有笔记
    专栏所有笔记如下:https://www.cnblogs.com/luoahong/p/10496701.html

    作者回复: 👍不容易

    
     3
  • 南山
    2019-09-09
    专栏最开始就订阅了,看到了这篇专栏目录中的这篇文档标题,当时就想着要从底层了解disruptor的原理,也一篇一篇认真的跟了下来,不知不觉就到了今天,虽然有很多后续还是要回去时常翻阅的知识点,但是也庆幸自己能一路跟着老师到现在。
         课后思考题会去翻源码再回来补充

    作者回复: 👍 Disruptor的代码短小精干,很适合深入读一读

    
     3
  • 唐朝农民
    2019-09-09
    ReentrantLock内部不也是CAS实现的吗

    作者回复: 并不是,ReentrantLock内部只是有CAS方法的调用而已,而这个调用是为了做状态检查和获取锁。

    ReetrantLock最终会调用AbstractQueuedSynchronizer,并且会在拿不到锁的时候会有让当前节点sleep的过程。

    这个可以深入读一下ReetrantLock的源码。

    本质上,ReentrantLock等于是在Java层面实现了一个跨平台的锁机制,它的底层调用用到了CAS方法而已。而不是直接基于CAS来设计队列。

    
     2
  • 姜戈
    2019-09-09
    LinkedBlockingQueue源码(JDK1.8)看了一下, 使用的是ReentrantLock和Condition来控制的,没发现老师说的synchronized关键字, 是不是哪里我忽略掉了?

    作者回复: 是我笔误了,是ReetrantLock,下面我给的对比示例也是ReentrantLock的。

    
     1
  • leslie
    2019-09-09
    学习中一步步跟进:越来越明白其实真正弄明白为何学习的中间层其实是操作系统和计算机原理;就像老师的课程中不少就和操作系统相关,而在此基础上可以衍生出一系列相关的知识。
           就像老师的2个TOP:存储与IO系统,应用篇分别就是一个向下一个向上;代码题对于不做纯代码超过5年的来说有点难,跟课再去学Java有点难且时间实在不够-毕竟运维的coding能力都偏差,不过大致能明白原理,从原理层去解释一些问题的根源原因,以及某些场合下那些可能更加适用。
          其实通过操作系统和组成原理会衍生出很多知识:选择合适的方向专攻确实不错。向老师提个小的要求:希望在最后一堂课可以分享老师在做这个专栏所查阅的主要书籍,毕竟没人可以学完一遍就基本掌握的;老师所看的核心资料是我们后续再看课程提升自己的一个辅助手段吧。
    展开

    作者回复: 从运维的角度,其实还有一个重要的主题是网络,也值得仔细关注一下。

    在专栏的每篇文章后面列了推荐阅读,也在一开始的学习方法的那一讲里面列了一些参考资料。可以先从这些看起。

    另外一个去处是去看Wikipedia对应的条目以及相关引用。

     1
     1
  • 曙光
    2019-10-22
    compxchg [ax] ,[bx], [cx]和 UNSAFE.compareAndSwapLong(this, VALUE_OFFSET, expectedValue, newValue)d对应关系没搞明白。jdk源码到compareAndSwapLong,只有
    @HotSpotIntrinsicCandidate
    public final native boolean compareAndSetLong(Object o, long offset,long expected,long x);
    不知道compxchg的[ax] ,[bx], [cx]和compareAndSetLong方法有什么对应关系
    展开
    
    
  • 免费的人
    2019-09-11
    Cas仍然会涉及到内存读取,老师能否介绍下rcu锁?

    作者回复: 是的,CAS仍然会涉及到内存读取。

    我之前没有仔细了解过RCU,今天简单看了一下资料,如果我的理解没有错的话。作为读写锁替代的话,是OK的。不过在Disruptor的场景下,Consumer需要的并不是一个读写锁,Producer和Consumer因为都需要更新自己的位置,其实是两个写锁。我直觉上觉得并没有办法依靠RCU的方式来解决。

    不过这个值得仔细想一下。

    
    
  • d
    2019-09-09
    看了下jdk 1.8的 AtomicLong 和disruptor的sequence, 个人认为有两点不同:
    1. disruptor 加了上一讲里面的padding, 以进一步利用缓存。
    2. Atomiclong 里面提供了更多的方法,并且判断cpu是否支持无锁cas
    相同点,底层都是调用unsafe类实现硬件层面的操作,以跳过jdk的限制。

    作者回复: 👍理解准确到位

    
    
  • 逍遥法外
    2019-09-09
    ReentrantLock内部也有CAS的操作,只不过也会有Lock的操作。Disruptor直接使用CAS,是简化了操作。

    作者回复: 👍 ReetrantLock里面的CAS是作为调用方式,最终来实现一个JVM上跨平台的锁的

    
    
我们在线,来聊聊吧