JUC原子类 根据修改的数据类型,可以将JUC包中的原子操作类可以分为4类。
基本类型 : AtomicInteger, AtomicLong, AtomicBoolean ;数组类型 : AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray ;引用类型 : AtomicReference, AtomicStampedRerence, AtomicMarkableReference ;对象的属性修改类型 : AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater 。
这些类存在的目的是对相应的数据进行原子操作。所谓原子操作,是指操作过程不会被中断,保证数据操作是以原子方式进行的。
AtomicLong介绍和函数列表 AtomicLong是作用是对长整形进行原子操作。 在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。
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 AtomicLong() AtomicLong(long initialValue) final void set (long newValue) final long get () final long decrementAndGet () final long getAndDecrement () final long incrementAndGet () final long getAndIncrement () final long addAndGet (long delta) final long getAndAdd (long delta) final boolean compareAndSet (long expect, long update) final long getAndSet (long newValue) int intValue () long longValue () float floatValue () double doubleValue () final void lazySet (long newValue) final boolean weakCompareAndSet (long expect, long update)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public final long incrementAndGet () { for (;;) { long current = get(); long next = current + 1 ; if (compareAndSet(current, next)) return next; } } 说明: (01 ) incrementAndGet()首先会根据get()获取AtomicLong对应的long 值。该值是volatile 类型的变量,get()的源码如下: (02 ) incrementAndGet()接着将current加1 ,然后通过CAS函数,将新的值赋值给value。
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 39 import java.util.concurrent.atomic.AtomicLong;public class LongTest { public static void main (String[] args) { AtomicLong mAtoLong = new AtomicLong (); mAtoLong.set(0x0123456789ABCDEFL ); System.out.printf(" s : 0x6X\n" , "get()" , mAtoLong.get()); System.out.printf(" s : 0x6X\n" , "intValue()" , mAtoLong.intValue()); System.out.printf(" s : 0x6X\n" , "longValue()" , mAtoLong.longValue()); System.out.printf(" s : %s\n" , "doubleValue()" , mAtoLong.doubleValue()); System.out.printf(" s : %s\n" , "floatValue()" , mAtoLong.floatValue()); System.out.printf(" s : 0x6X\n" , "getAndDecrement()" , mAtoLong.getAndDecrement()); System.out.printf(" s : 0x6X\n" , "decrementAndGet()" , mAtoLong.decrementAndGet()); System.out.printf(" s : 0x6X\n" , "getAndIncrement()" , mAtoLong.getAndIncrement()); System.out.printf(" s : 0x6X\n" , "incrementAndGet()" , mAtoLong.incrementAndGet()); System.out.printf(" s : 0x6X\n" , "addAndGet(0x10)" , mAtoLong.addAndGet(0x10 )); System.out.printf(" s : 0x6X\n" , "getAndAdd(0x10)" , mAtoLong.getAndAdd(0x10 )); System.out.printf("\n s : 0x6X\n" , "get()" , mAtoLong.get()); System.out.printf(" s : %s\n" , "compareAndSet()" , mAtoLong.compareAndSet(0x12345679L , 0xFEDCBA9876543210L )); System.out.printf(" s : 0x6X\n" , "get()" , mAtoLong.get()); } } get() : 0x0123456789ABCDEF intValue() : 0x0000000089ABCDEF longValue() : 0x0123456789ABCDEF doubleValue() : 8.1985529216486896E16 floatValue() : 8.1985531E16 getAndDecrement() : 0x0123456789ABCDEF decrementAndGet() : 0x0123456789ABCDED getAndIncrement() : 0x0123456789ABCDED incrementAndGet() : 0x0123456789ABCDEF addAndGet(0x10 ) : 0x0123456789ABCDFF getAndAdd(0x10 ) : 0x0123456789ABCDFF get() : 0x0123456789ABCE0F compareAndSet() : false get () : 0x0123456789ABCE0F
AtomicLongArray原子类 AtomicLongArray的作用则是对”长整形数组”进行原子操作。
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 AtomicLongArray(int length) AtomicLongArray(long [] array) long addAndGet (int i, long delta) boolean compareAndSet (int i, long expect, long update) long decrementAndGet (int i) long get (int i) long getAndAdd (int i, long delta) long getAndDecrement (int i) long getAndIncrement (int i) long getAndSet (int i, long newValue) long incrementAndGet (int i) void lazySet (int i, long newValue) int length () void set (int i, long newValue) String toString () boolean weakCompareAndSet (int i, long expect, long update)
AtomicLongArray示例
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 import java.util.concurrent.atomic.AtomicLongArray;public class LongArrayTest { public static void main (String[] args) { long [] arrLong = new long [] {10 , 20 , 30 , 40 , 50 }; AtomicLongArray ala = new AtomicLongArray (arrLong); ala.set(0 , 100 ); for (int i=0 , len=ala.length(); i<len; i++) System.out.printf("get(%d) : %s\n" , i, ala.get(i)); System.out.printf(" s : %s\n" , "getAndDecrement(0)" , ala.getAndDecrement(0 )); System.out.printf(" s : %s\n" , "decrementAndGet(1)" , ala.decrementAndGet(1 )); System.out.printf(" s : %s\n" , "getAndIncrement(2)" , ala.getAndIncrement(2 )); System.out.printf(" s : %s\n" , "incrementAndGet(3)" , ala.incrementAndGet(3 )); System.out.printf(" s : %s\n" , "addAndGet(100)" , ala.addAndGet(0 , 100 )); System.out.printf(" s : %s\n" , "getAndAdd(100)" , ala.getAndAdd(1 , 100 )); System.out.printf(" s : %s\n" , "compareAndSet()" , ala.compareAndSet(2 , 31 , 1000 )); System.out.printf(" s : %s\n" , "get(2)" , ala.get(2 )); } } get(0 ) : 100 get(1 ) : 20 get(2 ) : 30 get(3 ) : 40 get(4 ) : 50 getAndDecrement(0 ) : 100 decrementAndGet(1 ) : 19 getAndIncrement(2 ) : 30 incrementAndGet(3 ) : 41 addAndGet(100 ) : 199 getAndAdd(100 ) : 19 compareAndSet() : true get (2 ) : 1000
AtomicReference介绍和函数列表 AtomicReference是作用是对”对象”进行原子操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 AtomicReference() AtomicReference(V initialValue) boolean compareAndSet (V expect, V update) V get () V getAndSet (V newValue) void lazySet (V newValue) void set (V newValue) String toString () boolean weakCompareAndSet (V expect, V update)
1 2 3 AtomicReference的源码比较简单。它是通过"volatile" 和"Unsafe提供的CAS函数实现" 原子操作。 (01 ) value是volatile 类型。这保证了:当某线程修改value的值时,其他线程看到的value值都是最新的value值,即修改之后的volatile 的值。 (02 ) 通过CAS设置value。这保证了:当某线程池通过CAS函数(如compareAndSet函数)设置value时,它的操作是原子的,即线程在操作value时不会被中断。
AtomicReference示例
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 import java.util.concurrent.atomic.AtomicReference;public class AtomicReferenceTest { public static void main (String[] args) { Person p1 = new Person (101 ); Person p2 = new Person (102 ); AtomicReference ar = new AtomicReference (p1); ar.compareAndSet(p1, p2); Person p3 = (Person)ar.get(); System.out.println("p3 is " +p3); System.out.println("p3.equals(p1)=" +p3.equals(p1)); } } class Person { volatile long id; public Person (long id) { this .id = id; } public String toString () { return "id:" +id; } } 新建AtomicReference对象ar时,将它初始化为p1。 紧接着,通过CAS函数对它进行设置。如果ar的值为p1的话,则将其设置为p2。 最后,获取ar对应的对象,并打印结果。p3.equals(p1)的结果为false ,这是因为Person并没有覆盖equals()方法,而是采用继承自Object.java的equals()方法;而Object.java中的equals()实际上是调用"==" 去比较两个对象,即比较两个对象的地址是否相等。 p3 is id:102 p3.equals(p1)=false
AtomicLongFieldUpdater介绍和函数列表 AtomicLongFieldUpdater可以对指定”类的 ‘volatile long’类型的成员”进行原子更新。它是基于反射原理实现的。
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 protected AtomicLongFieldUpdater () long addAndGet (T obj, long delta) abstract boolean compareAndSet (T obj, long expect, long update) long decrementAndGet (T obj) abstract long get (T obj) long getAndAdd (T obj, long delta) long getAndDecrement (T obj) long getAndIncrement (T obj) long getAndSet (T obj, long newValue) long incrementAndGet (T obj) abstract void lazySet (T obj, long newValue) static <U> AtomicLongFieldUpdater<U> newUpdater (Class<U> tclass, String fieldName) abstract void set (T obj, long newValue) abstract boolean weakCompareAndSet (T obj, long expect, long update)
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 import java.util.concurrent.atomic.AtomicLongFieldUpdater;public class LongFieldTest { public static void main (String[] args) { Class cls = Person.class; AtomicLongFieldUpdater mAtoLong = AtomicLongFieldUpdater.newUpdater(cls, "id" ); Person person = new Person (12345678L ); mAtoLong.compareAndSet(person, 12345678L , 1000 ); System.out.println("id=" +person.getId()); } } class Person { volatile long id; public Person (long id) { this .id = id; } public void setId (long id) { this .id = id; } public long getId () { return id; } } id=1000