java并发J.U.C AtomicReference VS Volatile
SpinLock实现,摘自并发编程网
package com.juc.simple;
import java.util.concurrent.atomic.AtomicReference;
/**
 * a implement of spinlock based on  cas
 *
 */
public class SpinLock {
	private AtomicReference<Thread> sign = new AtomicReference<>();
	/**
	 * 让当前线程不停地的在循环体内执
	 * 当循环的条件被其他线程改变时 才能进入临界区
	 */
	public void lock() {
		Thread current = Thread.currentThread();
		//自旋,如果sign为null才能设置为current or memcachedb: checkandset
		while (!sign.compareAndSet(null, current)) {
		}
	}
	public void unlock() {
		Thread current = Thread.currentThread();
		sign.compareAndSet(current, null);
	}
}
这里是通过 AtomicReference实现的,而AtomicReference是通过volatile与Unsafe的CAS实现
volatile保证可见性,所有的线程看到的都是最新(主内存?)的值,但是volatile的操作不具有原子性,这样像(a++)这种操作就不能保证安全了,实际是读--修改--写操作的过程
AtomicReference的CAS操作更新值具有原子性
先来一段AtomicReference与volatile的比较
package com.juc.simple;
import java.util.concurrent.atomic.AtomicReference;
public class VolatileVsAtomicReference {
	private static volatile Integer volatileVar = 0;
	//初始值value为0
	private static AtomicReference<Integer> atomicReference=new AtomicReference<Integer>(volatileVar);
	public static void main(String[] args) {
		 try {
			testAtomicReference();
			testVolatile();
		} catch (InterruptedException e) {
			System.out.println(e.getMessage());
		}
	}
	public static void testAtomicReference() throws InterruptedException{
	    for (int i = 0; i < 1000; i++) {
	        new Thread(new Runnable(){
	            @Override
	            public void run() {
	                for (int i = 0; i < 1000; i++)
	                    while(true){
	                        Integer temp=atomicReference.get();
	                        if(atomicReference.compareAndSet(temp, temp+1)){
	                        	break;
	                        }
	                    }
	            }
	        }).start();
	    }
	    Thread.sleep(1000);
	    System.out.println("atomicReference "+atomicReference.get()); //1000000
	}
	public static void testVolatile() throws InterruptedException{
	    for (int i = 0; i < 1000; i++) {
	        new Thread(new Runnable(){
	            @Override
	            public void run() {
	                for (int i = 0; i < 1000; i++) {
	                	volatileVar=volatileVar++;
	                }
	            }
	        }).start();
	    }
	    Thread.sleep(1000);
	    System.out.println("volatileVar "+volatileVar); //may 8545
	}
}
结果:试过好几次volatileVar值都是不一样的
atomicReference 1000000
volatileVar 8545
这里可以看出如果用了CAS的话AtomicReference是可以保证原子性的,但如果只是简单的get()和set()方法是不行的,其实就等同于volatile,因为这货本身就是volatile实现的
参考
Java volatile reference vs. AtomicReference
get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.
AtomicReference的原代码实现
package java.util.concurrent.atomic;
import sun.misc.Unsafe;
/**
 * An object reference that may be updated atomically. See the {@link
 * java.util.concurrent.atomic} package specification for description
 * of the properties of atomic variables.
 * @since 1.5
 * @author Doug Lea
 * @param <V> The type of object referred to by this reference
 */
public class AtomicReference<V>  implements java.io.Serializable {
    private static final long serialVersionUID = -1848883965231344442L;
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;
    static {
      try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicReference.class.getDeclaredField("value"));
      } catch (Exception ex) { throw new Error(ex); }
    }
    //volatile 变量
    private volatile V value;
    /**
     * Creates a new AtomicReference with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicReference(V initialValue) {
        value = initialValue;
    }
    /**
     * Creates a new AtomicReference with null initial value.
     */
    public AtomicReference() {
    }
    /**
     * Gets the current value.
     *
     * @return the current value
     */
    public final V get() {
        return value;
    }
    /**
     * Sets to the given value.
     *
     * @param newValue the new value
     */
    //volatile变量赋值
    public final void set(V newValue) {
        value = newValue;
    }
    /**
     * Eventually sets to the given value.
     *
     * @param newValue the new value
     * @since 1.6
     */
    //设置为新的值
    public final void lazySet(V newValue) {
        unsafe.putOrderedObject(this, valueOffset, newValue);
    }
    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     * @param expect the expected value
     * @param update the new value
     * @return true if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    //如果当前值与期望值一致,则设置为新的值
    public final boolean compareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
    }
    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
     * and does not provide ordering guarantees, so is only rarely an
     * appropriate alternative to {@code compareAndSet}.
     *
     * @param expect the expected value
     * @param update the new value
     * @return true if successful.
     */
    public final boolean weakCompareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
    }
    /**
     * Atomically sets to the given value and returns the old value.
     *
     * @param newValue the new value
     * @return the previous value
     */
    //以原子方式设置为新的值,并且返回旧值
    public final V getAndSet(V newValue) {
        while (true) {
            V x = get();
            if (compareAndSet(x, newValue))
                return x;
        }
    }
    /**
     * Returns the String representation of the current value.
     * @return the String representation of the current value.
     */
    public String toString() {
        return String.valueOf(get());
    }
}
java并发J.U.C AtomicReference VS Volatile的更多相关文章
- Java并发J.U.C学习总结
		转载自http://www.cnblogs.com/chenpi/结合自己理解稍有添加自己的理解 阅读目录 JSR 166及J.U.C Executor框架(线程池. Callable .Future ... 
- java并发:线程同步机制之Volatile关键字&原子操作Atomic
		volatile关键字 volatile是一个特殊的修饰符,只有成员变量才能使用它,与Synchronized及ReentrantLock等提供的互斥相比,Synchronized保证了Synchro ... 
- Java并发编程、内存模型与Volatile
		http://www.importnew.com/24082.html volatile关键字 http://www.importnew.com/16142.html ConcurrentHash ... 
- Java并发编程学习笔记 深入理解volatile关键字的作用
		引言:以前只是看过介绍volatile的文章,对其的理解也只是停留在理论的层面上,由于最近在项目当中用到了关于并发方面的技术,所以下定决心深入研究一下java并发方面的知识.网上关于volatile的 ... 
- Java并发编程实战3-可见性与volatile关键字
		1. 缓存一致性问题 在计算机中,每条指令都是在CPU执行的,而CPU又不具备存储数据的功能,因此数据都是存储在主存(即内存)和外存(硬盘)中.但是,主存中数据的存取速度高于外存中数据的存取速度(这也 ... 
- Java并发-J.U.C之AQS
		AQS(Abstract Queue Synchronizer)介绍 [死磕Java并发]—–J.U.C之AQS(一篇就够了) 下面讲解具体的Java并发工具类 1 CountDownLatch 参考 ... 
- JAVA并发编程:相关概念及VOLATILE关键字解析
		一.内存模型的相关概念 由于计算机在执行程序时都是在CPU中运行,临时数据存在主存即物理内存,数据的读取和写入都要和内存交互,CPU的运行速度远远快于内存,会大大降低程序执行的速度,于是就有了高速缓存 ... 
- Java并发编程,3分分钟深入分析volatile的实现原理
		volatile原理 volatile简介 Java内存模型告诉我们,各个线程会将共享变量从主内存中拷贝到工作内存,然后执行引擎会基于工作内存中的数据进行操作处理. 线程在工作内存进行操作后何时会写到 ... 
- Java并发杂谈(一):volatile的底层原理,从字节码到CPU
		volatile的特性 volatile是Java中用于修饰变量的关键字,其主要是保证了该变量的可见性以及顺序性,但是没有保证原子性:其是Java中最为轻量级的同步关键字: 接下来我将会一步步来分析v ... 
随机推荐
- tftp服务器简单安装配置
			tftp服务器最简单安装配置 1.安装tftp-server sudo apt-get install tftpd-hpa sudo apt-get install tftp-hpa(如果不需要客户端 ... 
- JS判断网页是否在微信中打开/
			JS判断网页是否在微信中打开,代码如下: <script type="text/javascript"> function is_weixn(){ var ua = n ... 
- javac编译不同目录的源码提示找不到符号
			对于单个文件的且不引用其他类文件的java源码用javac编译大家都很熟悉即 javac mycode.java 但是如果这个文件引用到了其他的类文件,在进行编译的时候就会提示找不到符号,这时我们需要 ... 
- HDU4738 tarjan割边|割边、割点模板
			题目:http://acm.hdu.edu.cn/showproblem.php?pid=4738 坑点: 处理重边 图可能不连通,要输出0 若求出的结果是0,则要输出1,因为最少要派一个人 #inc ... 
- 静态界面传值javascript
			一:JavaScript静态页面值传递之URL篇能过URL进行传值.把要传递的信息接在URL上.Post.htm 复制代码代码如下: <input type="text" n ... 
- ur c题练习
			ur的c果然sxbk啊 ur5:“三个莫比乌斯反演掷地有声"——摘自v(c)f(z)k(y)语录,无删改 ur2:有根树分治裸题,复杂度玄学$O(n\sqrt{n})$. 首先,转化为统计k ... 
- poi2015 bzoj4377-4386训练
			就按时间顺序写吧 完成度:10/10 3.30 bzoj4385 首先一定是删去连续d个数,然后枚举终点,起点显然有单调性,用单调队列乱搞搞就可以啦 bzoj4378 首先才结论:可行当且仅当把所有大 ... 
- angular.extend用法实例
			angular.extend:依次将第二个参数及后续的参数的第一层属性(不管是简单属性还是对象)拷贝赋给第一个参数的第一层属性,即如果是对象,则是引用的是同一个对象,并返回第一个参数对象. 实例一 ... 
- Linux下的压缩和解压缩命令——jar
			原文链接:http://blog.chinaunix.net/uid-692788-id-2681136.htmlJAR包是Java中所特有一种压缩文档,其实大家就可以把它理解为.zip包.当然也是有 ... 
- java复杂枚举
			枚举以红绿灯为例,红灯30s后为绿灯,绿灯45s后为黄灯,黄灯5s后为红灯.具体的枚举代码如下: public enum TrafficLamp{ RED(30){ public TrafficLam ... 
