美文网首页
AtomicStampedReference和AtomicMar

AtomicStampedReference和AtomicMar

作者: 摆渡时光 | 来源:发表于2019-04-02 21:38 被阅读0次

一、AtomicStampedReference

其实像AtomicBoolean或AtomicLong等这样的变量在多线程修改时,都存在ABA的问题。所谓ABA问题类似于下面伪代码:

第一步 定义一个变量AtomicLong value值为1
第二步 Thread1修改value为2
第三步 Thread2修改value为1
第四步 Thread3通过判断value==1,来检查value是否被修改过

所以Thread3以为value没有被修改过,但实际已经被改过两次了,这就是ABA问题。因此AtomicStampedReference通过引入“版本”的概念,来解决上面的问题。看下面AtomicStampedReference类定义的变量:

    private static class Pair<T> {
        final T reference;
        final int stamp;
        private Pair(T reference, int stamp) {
            this.reference = reference;
            this.stamp = stamp;
        }
        static <T> Pair<T> of(T reference, int stamp) {
            return new Pair<T>(reference, stamp);
        }
    }

    private volatile Pair<V> pair;

reference即我们实际存储的变量,stamp是版本,每次修改可以通过+1保证版本唯一性。这样就可以保证每次修改后的版本也会往上递增。伪代码如下

第一步 定义一个变量AtomicStampedReference<Long> Pair.reference值为1, Pair.stamp设置为当前时间curTime
第二步 Thread1执行AtomicStampedReference.compareAndSet(1, 2, curTime, curTime+1)
第三步 Thread2执行AtomicStampedReference.compareAndSet(2, 1, curTime+1, curTime+2)
第四步 Thread3通过判断Pair.reference==1&&Pair.stamp==curTime,发现值虽然没有变,但是已经被修改了两次

二、AtomicMarkableReference

AtomicMarkableReference可以理解为上面AtomicStampedReference的简化版,就是不关心修改过几次,仅仅关心是否修改过。因此变量mark是boolean类型,仅记录值是否有过修改。

    private static class Pair<T> {
        final T reference;
        final boolean mark;
        private Pair(T reference, boolean mark) {
            this.reference = reference;
            this.mark = mark;
        }
        static <T> Pair<T> of(T reference, boolean mark) {
            return new Pair<T>(reference, mark);
        }
    }

    private volatile Pair<V> pair;

相关文章

网友评论

      本文标题:AtomicStampedReference和AtomicMar

      本文链接:https://www.haomeiwen.com/subject/uwwbbqtx.html