Java Concurrency 09--The use of atomic operation classes



  After java5, we have come into contact with the atomic operation of threads, that is, we only need to ensure that it is safe at that moment when modifying. After the corresponding packaging, the concurrent modification of the object can be processed. This article summarizes the Atomic series. Class usage methods, which include:

Types of Integer Long
basic type AtomicInteger AtomicLong AtomicBoolean
array type AtomicIntegerArray AtomicLongArray AtomicReferenceArray
Attribute Atom Modifier AtomicIntegerFieldUpdater AtomicLongFieldUpdater AtomicReferenceFieldUpdater

1. Use of basic types

  First look at the use of AtomicInteger, AtomicInteger is mainly for integer modification, take a look at the sample code:

public class AtomicIntegerDemo {

    /**
     * 常见的方法列表
     * @see AtomicInteger#get()             直接返回值
     * @see AtomicInteger#getAndAdd(int)    增加指定的数据,返回变化前的数据
     * @see AtomicInteger#getAndDecrement() 减少1,返回减少前的数据
     * @see AtomicInteger#getAndIncrement() 增加1,返回增加前的数据
     * @see AtomicInteger#getAndSet(int)    设置指定的数据,返回设置前的数据
     * 
     * @see AtomicInteger#addAndGet(int)    增加指定的数据后返回增加后的数据
     * @see AtomicInteger#decrementAndGet() 减少1,返回减少后的值
     * @see AtomicInteger#incrementAndGet() 增加1,返回增加后的值
     * @see AtomicInteger#lazySet(int)      仅仅当get时才会set
     * 
     * @see AtomicInteger#compareAndSet(int, int) 尝试新增后对比,若增加成功则返回true否则返回false
     */
    public final static AtomicInteger TEST_INTEGER = new AtomicInteger(1);

    public static void main(String []args) {

         for(int i = 0 ; i < 10 ; i++) { //开启10个线程

             new Thread() {
                 public void run() {
                     try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    int now = TEST_INTEGER.incrementAndGet(); //自增
                    System.out.println(Thread.currentThread().getName() + " get value : " + now);
                 }
             }.start();
         }
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

  Take a look at the results:

Thread-3 get value : 4
Thread-7 get value : 5
Thread-9 get value : 9
Thread-4 get value : 6
Thread-0 get value : 3
Thread-1 get value : 8
Thread-5 get value : 11
Thread-8 get value : 7
Thread-2 get value : 10
Thread-6 get value : 2

  It can be seen that the 10 threads are thread-safe and there is no conflict. That is to say, we can solve the thread safety problem by using the atomic operation class to operate the basic type int. When a thread is operating, it will exclude other threads, and we do not need to manually use synchronized to achieve mutual exclusion. AtomicLong is similar to AtomicBoolean, so I won't give an example.

2. The use of array types

  Let's start with Atomic's array usage. Atomic's array requires no modification of length, etc. It is not as rich in operations as collection classes, but it can make the operation of each element on the array absolutely safe, that is, its refinement strength Or to the elements on the array, do secondary packaging, although it is an array type, but in the end it still manipulates the number stored in the array, so if you know the above basic types, the array type is also easy to understand. Here we mainly look at the use of AtomicIntegerArray, and others are similar.

public class AtomicIntegerArrayTest {

    /**
     * 常见的方法列表
     * @see AtomicIntegerArray#addAndGet(int, int) 执行加法,第一个参数为数组的下标,第二个参数为增加的数量,返回增加后的结果
     * @see AtomicIntegerArray#compareAndSet(int, int, int) 对比修改,参数1:数组下标,参数2:原始值,参数3,修改目标值,修改成功返回true否则false
     * @see AtomicIntegerArray#decrementAndGet(int) 参数为数组下标,将数组对应数字减少1,返回减少后的数据
     * @see AtomicIntegerArray#incrementAndGet(int) 参数为数组下标,将数组对应数字增加1,返回增加后的数据
     * 
     * @see AtomicIntegerArray#getAndAdd(int, int) 和addAndGet类似,区别是返回值是变化前的数据
     * @see AtomicIntegerArray#getAndDecrement(int) 和decrementAndGet类似,区别是返回变化前的数据
     * @see AtomicIntegerArray#getAndIncrement(int) 和incrementAndGet类似,区别是返回变化前的数据
     * @see AtomicIntegerArray#getAndSet(int, int) 将对应下标的数字设置为指定值,第二个参数为设置的值,返回是变化前的数据
     */
    private final static AtomicIntegerArray ATOMIC_INTEGER_ARRAY = new AtomicIntegerArray(new int[]{1,2,3,4,5,6,7,8,9,10});

    public static void main(String []args) throws InterruptedException {
        Thread []threads = new Thread[10];
        for(int i = 0 ; i < 10 ; i++) {
            final int index = i;
            final int threadNum = i;
            threads[i] = new Thread() {
                public void run() {
                    int result = ATOMIC_INTEGER_ARRAY.addAndGet(index, index + 1);
                    System.out.println("线程编号为:" + threadNum + " , 对应的原始值为:" + (index + 1) + ",增加后的结果为:" + result);
                }
            };
            threads[i].start();
        }
        for(Thread thread : threads) {
            thread.join();
        }
        System.out.println("=========================>\n执行已经完成,结果列表:");
        for(int i = 0 ; i < ATOMIC_INTEGER_ARRAY.length() ; i++) {
            System.out.println(ATOMIC_INTEGER_ARRAY.get(i));
        }
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

  The result of the operation is to add the same value to each array element, and they do not affect each other.

3. Use as a class attribute

  When a data type is an attribute in a class, and then we want to manipulate the data, we need to use the attribute atomic modifier. Here we take Integer as an example, namely: AtomicIntegerFieldUpdater. The sample code is as follows:

public class AtomicIntegerFieldUpdaterTest {  

    static class A {  
        volatile int intValue = 100;  
    }  

    /** 
     * 可以直接访问对应的变量,进行修改和处理 
     * 条件:要在可访问的区域内,如果是private或挎包访问default类型以及非父亲类的protected均无法访问到 
     * 其次访问对象不能是static类型的变量(因为在计算属性的偏移量的时候无法计算),也不能是final类型的变量(因为根本无法修改),必须是普通的成员变量 
     *  
     * 方法(说明上和AtomicInteger几乎一致,唯一的区别是第一个参数需要传入对象的引用) 
     * @see AtomicIntegerFieldUpdater#addAndGet(Object, int) 
     * @see AtomicIntegerFieldUpdater#compareAndSet(Object, int, int) 
     * @see AtomicIntegerFieldUpdater#decrementAndGet(Object) 
     * @see AtomicIntegerFieldUpdater#incrementAndGet(Object) 
     *  
     * @see AtomicIntegerFieldUpdater#getAndAdd(Object, int) 
     * @see AtomicIntegerFieldUpdater#getAndDecrement(Object) 
     * @see AtomicIntegerFieldUpdater#getAndIncrement(Object) 
     * @see AtomicIntegerFieldUpdater#getAndSet(Object, int) 
     */  
    public final static AtomicIntegerFieldUpdater<A> ATOMIC_INTEGER_UPDATER = AtomicIntegerFieldUpdater.newUpdater(A.class, "intValue");  

    public static void main(String []args) {  
        final A a = new A();  
        for(int i = 0 ; i < 10 ; i++) {  

            new Thread() {  
                public void run() {  
                    if(ATOMIC_INTEGER_UPDATER.compareAndSet(a, 100, 120)) {  
                        System.out.println(Thread.currentThread().getName() + " 对对应的值做了修改!");  
                    }  
                }  
            }.start();  
        }  
    }  
}  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

  It can be seen that the class and class attributes need to be passed in here. After passing in, it is no different from the previous operation of Integer. The essence is the same. After running it, only one thread can modify it.
  The use of the atomic operation class of threads is briefly summarized here. The principles of other operation classes are similar. You can refer to the JDK documentation, and you can easily write the corresponding test code.
  
  Related reading: http://blog.csdn.net/column/details/bingfa.html




  After java5, we have come into contact with the atomic operation of threads, that is, we only need to ensure that it is safe at that moment when modifying. After the corresponding packaging, the concurrent modification of the object can be processed. This article summarizes the Atomic series. Class usage methods, which include:

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326877496&siteId=291194637