1.volatile并不能保证线程安全性
声明为volatile的线程共享变量,并不能保证多线程在修改它值的时候,是安全的。
测试代码如下:
package com.wind.DbTec.sqlpkg; /** * volatile变量的正确用法 volatile变量不能保证变量修改的原子性,需要原子类的协助 基于解析可看链接地址 * http://www.cnblogs.com/yakun/p/3589437.html * http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html * http://www.blogjava.net/mstar/archive/2013/04/24/398351.html * * @author zhouyanjun * @version 1.0 2014-12-10 */ public class VolatileTest extends Thread { static class VolatileRunnable implements Runnable { private volatile Integer value = 0; public void run() { for (;;) { if (value >= 1000) { break; } value += 1; System.out.println(Thread.currentThread().getName() + " " + value); } } } public static void main(String[] args) { VolatileRunnable volatileRunnable = new VolatileRunnable(); Thread thread1 = new Thread(volatileRunnable); Thread thread2 = new Thread(volatileRunnable); Thread thread3 = new Thread(volatileRunnable); Thread thread4 = new Thread(volatileRunnable); thread1.start(); thread2.start(); thread3.start(); thread4.start(); } }
如上述代码,声明了一个线程共享的volatile的变量value,并在线程处理中累加它的值,同时启动4个线程,我们来看打印出的value值是否有相同值,如果有相同则表明volatile变量并不能保证线程安全。
笔者在多次执行下来,确实存在有相同值的情况(结果集太长就不贴出来了),所以volatile变量并不能保证线程安全。读者也可以自己测试下。
2.如何能使volatile变量线程安全呢?
要使volatile变量线程安全,是可以做到的,需要配合一些原子类的实现。比如笔者下面使用AtomicReferen-ceFieldUpdater类修改的上述代码,就可以保证volatile变量的线程安全。代码如下:
package com.wind.DbTec.sqlpkg; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; /** * volatile变量的正确用法 volatile变量不能保证变量修改的原子性,需要原子类的协助 基于解析可看链接地址 * http://www.cnblogs.com/yakun/p/3589437.html * http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html * http://www.blogjava.net/mstar/archive/2013/04/24/398351.html * * @author zhouyanjun * @version 1.0 2014-12-10 */ public class VolatileTest extends Thread { static class VolatileRunnable implements Runnable { private static final AtomicReferenceFieldUpdater<VolatileRunnable, Integer> nextUpdater = AtomicReferenceFieldUpdater .newUpdater(VolatileRunnable.class, Integer.class, "value"); // 增加一个AtomicReferenceFieldUpdater private volatile Integer value = 0; public void run() { for (;;) { if (value >= 1000) { break; } // 递增value当前值 Integer current = value; while (!nextUpdater.compareAndSet(this, current, current + 1)) { // 判断value值是否跟原值一样,一样则修改value值为current+1 current = value; } System.out.println(Thread.currentThread().getName() + " " + value); } } } public static void main(String[] args) { VolatileRunnable volatileRunnable = new VolatileRunnable(); Thread thread1 = new Thread(volatileRunnable); Thread thread2 = new Thread(volatileRunnable); Thread thread3 = new Thread(volatileRunnable); Thread thread4 = new Thread(volatileRunnable); thread1.start(); thread2.start(); thread3.start(); thread4.start(); } }
这种情况下,笔者多次测试下来,确实没出现相同值的情况,保证了volatile值的线程安全性。具体AtomicR-eferenceFieldUpdater类的实现可以从java.util.concurrent.atomic包下找到。
其实java.util.concurrent.atomic包下针对int,long,boolean,reference实现了好几个原子类,比如AtomicInteg-er,AtomicLong等。他们的原子更新方法实现,跟上述代码其中的这段很相似
Integer current = value; while (!nextUpdater.compareAndSet(this, current, current + 1)) { // 判断value值是否跟原值一样,一样则修改value值为current+1 current = value; }
比如AtomicInteger,它的值保存在成员变量value中,而且value是个volatile变量,如下:
private volatile int value;
它的getAndSet方法(此方法是返回当前值,然后设置新值)实现如下:
/** * Atomically sets to the given value and returns the old value. * * @param newValue the new value * @return the previous value */ public final int getAndSet(int newValue) { for (;;) { int current = get(); if (compareAndSet(current, newValue)) return current; } }
3.为什么volatile还需要配置原子类才能保证线程安全?
这个原因可能需要细究到java虚拟机的实现中去,笔者暂且止步,再次记一笔,以后有机会再做细究。
相关推荐
java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java ...
java volatile 关键字 学习
从JUC中的AQS引入,讲解Java volatile与AQS锁内存可见性
主要介绍了Java Volatile 变量详解及使用方法的相关资料,需要的朋友可以参考下
主要介绍了java volatile关键字使用方法及注意事项的相关资料,当一个变量被声明为 volatile 后,java 内存模型确保所有使用该变量的线程能看到相同的、一致的值。,需要的朋友可以参考下
在本文里我们给大家分享的是关于java volatile关键字作用及使用场景的相关知识点内容,需要的朋友们学习下。
【Java面试题】volatile的作用
主要介绍了简单了解volatile关键字实现的原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
主要介绍了了解java volatile,volatile是Java提供的一种轻量级的同步机制,在并发编程中,它也扮演着比较重要的角色。下面我们来一起学习一下吧
主要介绍了java volatile关键字的含义详解的相关资料,需要的朋友可以参考下
主要介绍了Java Volatile关键字实现原理过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
在本文里我们给大家整理了一篇关于Java volatile的适用场景实例内容和知识点,需要的朋友们可以学习下。
主要介绍了Java Volatile关键字同步机制详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
主要讲述java线程volatile关键字
主要介绍了java 高并发中volatile的实现原理的相关资料,在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”,需要的朋友...
本篇文章给大家通过实例分享了Java中Volatile的作用,有兴趣的朋友可以学习参考下。
volatile这个关键字,不仅仅在Java语言中有,在很多语言中都有的,而且其用法和语义也都是不尽相同的。这篇文章主要介绍了Java中的volatile关键字,需要的朋友可以参考下