转载自:https://segmentfault.com/a/1190000015831791?utm_source=tag-newest#articleHeader0

就是以原子方式更新对象引用。

可以看到它持有一个对象的引用,-value,用volatile修饰,并通过unsafe类来操作该引用。

 1 private static final Unsafe unsafe = Unsafe.getUnsafe();
 2     private static final long valueOffset;
 3 
 4     static {
 5       try {
 6         valueOffset = unsafe.objectFieldOffset
 7             (AtomicReference.class.getDeclaredField("value"));
 8       } catch (Exception ex) { throw new Error(ex); }
 9     }
10 
11     private volatile V value;
12 
13     /**
14      * Creates a new AtomicReference with the given initial value.
15      *
16      * @param initialValue the initial value
17      */
18     public AtomicReference(V initialValue) {
19         value = initialValue;
20     }
21 
22     /**
23      * Creates a new AtomicReference with null initial value.
24      */
25     public AtomicReference() {
26     }

为什么需要AtomicReference?难道多个线程同时对一个引用变量赋值也会出现并发问题?
引用变量的赋值本身没有并发问题,也就是说对于引用变量var ,类似下面的赋值操作本身就是原子操作:
Foo var = ... ;
AtomicReference的引入是为了可以用一种类似乐观锁的方式操作共享资源,在某些情景下以提升性能。

我们知道,当多个线程同时访问共享资源时,一般需要以加锁的方式控制并发:

volatile Foo sharedValue = value;
Lock lock = new ReentrantLock();

lock.lock();
try{
    // 操作共享资源sharedValue
}
finally{
    lock.unlock();
}

上述访问方式其实是一种对共享资源加悲观锁的访问方式。

而AtomicReference提供了以无锁方式访问共享资源的能力,看看如何通过AtomicReference保证线程安全,来看个具体的例子:

 1 package com.citi.test.mutiplethread.demo0503;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import java.util.concurrent.atomic.AtomicReference;
 6 
 7 public class AtomicReferenceTest {
 8     public static void main(String[] args) throws InterruptedException {
 9         AtomicReference<Integer> ref=new AtomicReference<Integer>(new Integer(1000));
10         List<Thread> list=new ArrayList<Thread>();
11         for(int i=0;i<1000;i++){
12             Thread t=new Thread(new Task(ref),"Thread-"+i);
13             list.add(t);
14             t.start();
15         }
16         for(Thread t: list){
17             System.out.println(t.getName());
18             t.join();
19         }
20         System.out.println(ref.get());
21     }
22 }
23 class Task implements Runnable{
24     private AtomicReference<Integer> ref;
25     public Task(AtomicReference<Integer> ref) {
26         this.ref=ref;
27     }
28     @Override
29     public void run() {
30         for(;;){
31             Integer oldV=ref.get();
32             System.out.println(Thread.currentThread().getName()+":"+oldV);
33             if(ref.compareAndSet(oldV, oldV+1)){
34                 break;
35             }
36         }
37     }
38 }
View Code

相关文章: