精华内容
下载资源
问答
  • Java原子操作类

    2020-01-07 23:28:25
    原子操作类 原子基本类型 原子数组类型 原子引用类型 原子更新字段类型 原子操作类 JDK1.5开始提供了java.util.concurrent.atomic包,包下13个类,属于4种类型的原子更新方式,分别是原子更新基本类型、原子...

    目录

    原子操作类

    原子基本类型

    原子数组类型

    原子引用类型

    原子更新字段类型


    原子操作类

    JDK1.5开始提供了java.util.concurrent.atomic包,包下13个类,属于4种类型的原子更新方式,分别是原子更新基本类型、原子更新数组、原子更新引用和原子更新属性(字段)。JDK1.8新增了DoubleAccumulator、LongAccumulator、DoubleAdder、LongAdder,还有一个做为父类的Striped64,的针对高并发环境下效率有所提高。

    原子基本类型

    Java提供了AtomicInteger、AtomicBoolean、AtomicLong三个类,以AtomicInteget为例。

    方法 描述
    void lazySet(int newValue) 最终会设置成newValue,使用lazySet设置值后,可能导致其他线程在之后的一段时间内还是可以读到旧的值。(但是JDK 1.11目前Integer和Long用的是putIntVolatile和putLongVolatile,既支持volatile store语义,保证刷新到主存。Boolean则用的是普通的替换,和VarHandlesAPI的setRelease方法,和描述一致。)
    int getAndSet(int newValue) 以原子的方式设置为newValue的值,并返回旧值。
    boolean compareAndSet(int expect, int update) 如果输入的数值等于预期值,则以原子方式将该值设置为输入的值。
    int getAndIncrement() 以原子的方式将当前值加1,注意,这里返回的是自增的值。
    int addAndGet(int delta) 以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加,并返回结果。
        
        public final void lazySet(int newValue) {
            U.putIntRelease(this, VALUE, newValue);
        }
    
        @HotSpotIntrinsicCandidate
        public final void putIntRelease(Object o, long offset, int x) {
            this.putIntVolatile(o, offset, x);
        }
    
        //支持volatile store语义
        @HotSpotIntrinsicCandidate
        public native void putIntVolatile(Object var1, long var2, int var4);
    
    
        public final int getAndSet(int newValue) {
            //循环CAS
            return U.getAndSetInt(this, VALUE, newValue);
        }
    
        public final boolean compareAndSet(int expectedValue, int newValue) {
            //CAS
            return U.compareAndSetInt(this, VALUE, expectedValue, newValue);
        }
    
        public final int getAndIncrement() {
            //循环CAS
            return U.getAndAddInt(this, VALUE, 1);
        }
    
        public final int addAndGet(int delta) {
            //循环CAS
            return U.getAndAddInt(this, VALUE, delta) + delta;
        }
    

    原子数组类型

    Java提供了AtomicIntergerArray、AtomicLongArray、AtomicRefenceArray三个类,以AtomicIntergerArray为例。

            AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[10]);
            atomicIntegerArray.getAndSet(0, 3);
            System.out.println(atomicIntegerArray.get(0));

    原子引用类型

    Java提供了AtomicReference(原子更新引用类型)、AtomicReferenceFieldUpdater(原子更新引用类型里的字段)、AtomicMarkableReference(原子更新带有标记位的引用类型)三个类,以AtomicRefence为例。

        static class User {
            private String name;
            private int old;
    
            public User(String name, int old) {
                this.name = name;
                this.old = old;
            }
        }
    
        public static void main(String[] args) {
            User user = new User("小明", 11);
            AtomicReference<User> userAtomicReference = new AtomicReference<>();
            userAtomicReference.set(user);
    
            User user1 = new User("小红", 12);
            userAtomicReference.compareAndSet(user, user1);
            System.out.println(userAtomicReference.get().name);
            System.out.println(userAtomicReference.get().old);
        }

    原子更新字段类型

    原子地更新字段类需要两步。

    1. 第一步,因为原子更新字段类都是抽象类,每次使用地时候必须使用静态方法newUpdater()创建一个更新器,并且需要设置想要更新地类和属性。

    2. 第二步,更新类的字段(属性)必须使用public volatile修饰符。

    Java提供了AtomicIntegerFieldUpdater(原子更新整型的字段的更新器)、AtomicLongFieldUpdater(原子更新长整型的字段的更新器)、AtomicStampedRefence(原子更新带有版本号的引用类型)三个类。以AtomicIntegerFieldUpdater为例。

        static class User {
            private String name;
            private volatile int old;
    
            public User(String name, int old) {
                this.name = name;
                this.old = old;
            }
        }
    
        public static void main(String[] args) {
            AtomicIntegerFieldUpdater<User> userUpdater = AtomicIntegerFieldUpdater.newUpdater(User.class, "old");
            User user = new User("小明", 11);
            System.out.println(userUpdater.getAndIncrement(user));
            System.out.println(userUpdater.get(user));
        }

     

    展开全文
  • java原子操作类

    2020-08-18 10:59:49
    Java从JDK1.5开始提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单,性能高效,线程安全地更新一个变量的方式。在Java并发比编程中,要想保证一些操作不被其他线程干扰,就需要保证...

    背景

    Java从JDK1.5开始提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单,性能高效,线程安全地更新一个变量的方式。在Java并发比编程中,要想保证一些操作不被其他线程干扰,就需要保证原子性

     

    1、原子更新基本类型类:

    • AtomicBoolean:原子更新布尔类型。
    • AtomicInteger:原子更新整型。
    • AtomicLong: 原子更新长整型。

      以上3个类提供的方法几乎一模一样,所以仅以AtomicInteger为例进行详解。

    • int addAndGet(int delta):以原子方式将输入的数值与实例中的值相加,并返回结果。
    • boolean compareAndSet(int expect, int update):如果输入的数值等于预期值,则以原子方式将该值设置为输入的值。
    • int getAndIncrement():以原子方式将当前值加1,注意这里返回的是自增前的值。
    • void lazySet(int newValue):最终会设置成newValue。
    • int getAndSet(int newValue):已原子方式设置值为newValue, 并返回旧值

    实列:

    import java.util.concurrent.atomic.AtomicInteger;
    
    public class MyAtomicTest {
        public static void main(String[] arg)
        {
            AtomicInteger atomicInteger=new AtomicInteger(123);
            System.out.println(atomicInteger.getAndIncrement());
            atomicInteger.getAndSet(345);
            System.out.println(atomicInteger.get());
        }
    }
    结果:
    123
    345
    
    进程已结束,退出代码 0

    2、原子更新数组:

    • AtomicIntegerArray:原子更新整形数组。
    • AtomicLongArray:原子更新长整型数组。
    • AtomicReferenceArray:原子更新引用类型数组里的元素。

    这三个类的最常用的方法是如下两个方法:
      (1)get(int index):获取索引为index的元素值。
      (2)compareAndSet(int i,E expect,E update): 如果当前值等于预期值,则以原子方式将数组位置i的元素设置为update值。

     

     

    3、原子更新引用类型:

      原子更新基本类型的AtomicInteger,只能更新一个变量。如果要原子更新多个变量,就需要使用这个原子更新引用类型提供的类,包含以下三个。

    • AtomicReference:原子更新引用类型
    • AtomicReferenceFieldUpdater:原子更新引用类型里的字段
    • AtomicMarkableReference:原子更新带有标记位的引用类型。

    这三个类提供的方法都差不多,首先构造一个引用对象,然后把引用对象set进Atomic类,然后调用compareAndSet等一些方法去进行原子操作,原理都是基于Unsafe实现,但AtomicReferenceFieldUpdater略有不同,更新的字段必须用volatile修饰

     

    4、原子更新字段类:

    • AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
    • AtomicLongFieldUpdater:原子更新长整型字段的更新器。
    • AtomicStampedReference:原子更新带有版本号的引用类型。

     这四个类的使用方式都差不多,示例代码如上一小节的AtomicReferenceFieldUpdater一样,要想原子地更新字段类需要两步。第一步,因为原子更新字段类都是抽象类,每次使用的时候必须使用静态方法newUpdater()创建一个更新器,并且需要设置想要更新的类和属性。第二步,更新类的字段必须使用public volatile修饰

     

     

    展开全文
  • JAVA 原子操作类

    2018-11-13 11:27:00
    上文中,guava代码中就用到了,在这里再专门捋一下 部分内容源自: ...https://www.yiibai.com/java_concurrency/concurrency_atomiclong.html AtomicReferenceArray<ReferenceEntry<K, V>&g...

    上文中,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问题

     

    转载于:https://www.cnblogs.com/it-worker365/p/9951284.html

    展开全文
  • JAVA原子操作类解析

    2021-03-11 14:42:46
    JAVA原子操作类解析原理变量操作类 原理变量操作类 AtomicInteger、AtomicLong等。 主要原理:底层使用Unsafe对内部变量进行操作 存在的问题:当并发量比较高的情况下,同时竞争同一个原子变量,会导致由于只有一个...

    JAVA原子操作类解析

    原理变量操作类

    AtomicInteger、AtomicLong等。

    主要原理:底层使用Unsafe对内部变量进行操作

    存在的问题:当并发量比较高的情况下,同时竞争同一个原子变量,会导致由于只有一个CAS操作会成功,导致大量线程空转,消耗cpu资源。
    解决方法:JDK8中新增的原子操作类LongAdder,解决思路:AtomicLong的性能瓶颈是有多线程同时去竞争一个变量的更新而产生的,那么如果把一个变量分解成多个变量,让同样多的线程去竞争多个资源,最后获取LongAdder当前值时,是把所有的值累加到一起并返回。

    展开全文
  • Java原子操作类汇总

    2018-07-29 14:25:52
    Java原子操作类汇总  当程序更新一个变量时,如果是多线程同时更新这个变量,可能得到的结果与期望值不同。比如:有一个变量i,A线程执行i+1,B线程也执行i+1,经过两个线程的操作后,变量i的值可能不是期望的3,...
  • 1.原子更新基本类型类 2.原子更新数组 3.原子更新引用 ... 1 java 原子操作类Atomic ... 3 java.util.concurrent.atomic里的原子操作类提供了线程安全地更新一个变量的方式 4 4大类型13个原子操作类 5 ...
  • Java 原子操作类 Atomic

    2021-03-03 17:16:58
    Java从JDK1.5 开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。 Atomic包大致可以分为4类 原子更新基本类型 ...
  • 原子操作类,赋值操作要么成功,要么失败,没有中间态 public void testAtomic() { AtomicBoolean atomicBoolean = new AtomicBoolean(); AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(1); ...
  • java还提供了通过原子方式更新数组里的某个元素,Atomic包提供了以下4个。 AtomicIntegerArray:原子更新整型数组里的元素 AtomicLongArray:原子更新长整型数组里的元素 AtomicReferenceArray:原子更新引用类型...
  • 这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。 Atomic包下的这些类都是采用乐观锁策略CAS(又称为无锁操作)来更新数据的:假设所有线程访问共享资源的时候不会出现冲突,...
  • 版权声明:如果您觉得此文对您有帮助,...为什么需要AtomicInteger原子操作类? 对于Java中的运算操作,例如自增或自减,若没有进行额外的同步操作,在多线程环境下就是线程不安全的。num++解析为num=num+1,明显,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,335
精华内容 1,334
关键字:

java原子操作类

java 订阅