zoukankan      html  css  js  c++  java
  • JAVA 原子操作类

    上文中,guava代码中就用到了,在这里再专门捋一下

    部分内容源自:

    https://www.jianshu.com/p/712681f5aecd

    https://www.yiibai.com/java_concurrency/concurrency_atomiclong.html

    AtomicReferenceArray<ReferenceEntry<K, V>>
    根据变量类型的不同,Atomic包中的这12个原子操作类可以分为4种类型:
    ①原子更新基本类型AtomicBoolean、AtomicInteger、AtomicLong
    ②原子更新数组AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
    ③原子更新引用AtomicReference、AtomicReferenceFiledUpdater、AtomicMarkableReference
    ④原子更新字段(属性)AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference
    它们都是使用Unsafe实现的包装类。
     
    对于原子更新类基本操作,可以看到AtomicInteger中基本有以下一些方法,其他也都差不多,用法简单
            Executor executor = Executors.newFixedThreadPool(3);
            AtomicInteger atomicInteger = new AtomicInteger(0);
            for(int i = 0; i < 10; i++){
                executor.execute(()->{
                    System.out.println("atomicInteger的当前值:" + atomicInteger.addAndGet(1));
                });
            }

    原子更新数组,例AtomicReferenceArray,用法抄自上文,实际就是基于cas的操作

    public class MainTest {
        private static String[] source = new String[10];
        private static AtomicReferenceArray<String> atomicReferenceArray = new AtomicReferenceArray<String>(source);
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < atomicReferenceArray.length(); i++) {
                atomicReferenceArray.set(i, "item-2");
            }
    
            Thread t1 = new Thread(new Increment());
            Thread t2 = new Thread(new Compare());
            t1.start();
            t2.start();
    
            t1.join();
            t2.join();
        }
    
        static class Increment implements Runnable {
            public void run() {
                for (int i = 0; i < atomicReferenceArray.length(); i++) {
                    String add = atomicReferenceArray.getAndSet(i, "item-" + (i + 1));
                    System.out.println("Thread " + Thread.currentThread().getId() + ", index " + i + ", value: " + add);
                }
            }
        }
    
        static class Compare implements Runnable {
            public void run() {
                for (int i = 0; i < atomicReferenceArray.length(); i++) {
                    System.out.println("Thread " + Thread.currentThread().getId() + ", index " + i + ", value: "
                            + atomicReferenceArray.get(i));
                    boolean swapped = atomicReferenceArray.compareAndSet(i, "item-2", "updated-item-2");
                    System.out.println("Item swapped: " + swapped);
                    if (swapped) {
                        System.out
                                .println("Thread " + Thread.currentThread().getId() + ", index " + i + ", updated-item-2");
                    }
                }
            }
        }
    }

    AtomicReferenceFiledUpdater https://github.com/aCoder2013/blog/issues/10 这个blog写的真不错,在jdk中有很多应用。比如对buf的更新等

    一个基于反射的工具类,它能对指定类的指定的volatile引用字段进行原子更新。(注意这个字段不能是private的) 

     class Node {
       private volatile Node left, right;
    
       private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
         AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
       private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
         AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
    
       Node getLeft() { return left; }
       boolean compareAndSetLeft(Node expect, Node update) {
         return leftUpdater.compareAndSet(this, expect, update);
       }
       // ... and so on
     }}
    public
    class BufferedInputStream extends FilterInputStream {
    
        protected volatile byte buf[];
    
        /*
        *  原子的更新内部数组,比如扩容、关闭时,
        */
        private static final
            AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
            AtomicReferenceFieldUpdater.newUpdater
            (BufferedInputStream.class,  byte[].class, "buf");
    
    
        public void close() throws IOException {
            byte[] buffer;
            while ( (buffer = buf) != null) {
                //放在一个循环中,如果CAS更新失败,那么就读取最新的buf引用,继续CAS更新
                if (bufUpdater.compareAndSet(this, buffer, null)) {
                    InputStream input = in;
                    in = null;
                    if (input != null)
                        input.close();
                    return;
                }
            }
        }
    }

    AtomicStampedReference 通过包装[E,Integer]的元组来对对象标记版本戳stamp,从而避免ABA问题

  • 相关阅读:
    SendMessage 和 SendMessageTimeout 可能存在异常(除超时)
    类型强制转换符 与 + 符的优先级
    茵茵的第一课
    C小加 之 随机数
    16进制的简单运算
    交换输出
    计算球体积
    a letter and a number
    A problem is easy
    Coin Test
  • 原文地址:https://www.cnblogs.com/it-worker365/p/9951284.html
Copyright © 2011-2022 走看看