构建了100个线程, Volatile变量具有 synchronized 的可见性特性,但是不具备原子特性。
同时访问操作i,如果i在使用i++时候是对自身变量的操作,实际它这样的操作不是原子操作。下边我们用一段代码试试。
/**
* Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。这两种机制的提出都是为了实现代码线程的安全性。 其中 Volatile
* 变量的同步性较差(但有时它更简单并且开销更低),而且其使用也更容易出错。
*
* @author Janle
*
*/
public class volatile关键字 {
public static void main(String[] args) {
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// 建立100个线程
threads[i] = new ThreadVolatile();
for (int i = 0; i < threads.length; i++)
// 运行刚才建立的100个线程
threads[i].start();
for (int i = 0; i < threads.length; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 如果对n的操作是原子级别的,最后输出的结果应该为n=1000,很多时侯输出的n都小于1000.这说明n=n+1不是原子级别的操作。
* 原因是声明为volatile的简单变量如果当前值由该变量以前的值相关,那么volatile关键字不起作用,
* 也就是说如下的表达式都不是原子操作:
* n = n + 1;
* n++;
*/
System.out.println("n=" + ThreadVolatile.n);
}
}
class ThreadVolatile extends Thread {
public static volatile int n = 0;
public static synchronized void inc() {
n++;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
/**
* 这里注意:
* 当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,
* 如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。
*/
//n = n + 1;
inc();//// n = n + 1 改成了 inc();使用这个才能保证是原来的操作,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作
sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
总结:
用写操作时候不能依赖于当前值【当前获得的值不能被修改】。
该变量没有包含在具有其他变量的计算公式中。
volatile修饰设计用来修饰被不同线程访问和修改的变量。如果不加入volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。
分享到:
相关推荐
volatile关键字相信了解Java多线程的读者都很清楚它的作用。volatile关键字用于声明简单类型变量,下面看一下为什么要慎重使用volatile关键字
volatile是JVM提供的一种最轻量级的同步机制,因为Java内存模型为volatile定义特殊的访问规则,使其可以实现Java内存模型中的两大特性...这篇文章主要介绍了Java多线程之volatile关键字及内存屏障,需要的朋友可以参考下
线程安全、volatile关键字、原子性、并发包、死锁、线程池学习笔记
主要介绍了Java多线程 volatile关键字详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
本篇文章对内存栅栏与volatile关键字的使用进行了详细的分析介绍,需要的朋友参考下
本文详细解读一下volatile关键字如何保证变量在多线程之间的可见性,对Java中volatile关键字实现原理感兴趣的朋友一起通过本文学习吧
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候可以万事大吉。 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 ...
volatile 关键字是一个神秘的关键字,也许在 J2EE 上的 JAVA 程序员会了解多一点,但在 Android 上的 JAVA 程序员大多不了解这个关键字。只要稍了解不当就好容易导致一些并发上的错误发生,例如好多人把 volatile ...
C/C++中的volatile关键字和const对应,用来修饰变量,用于告诉编译器该变量值是不稳定的,可能被更改。使用volatile注意事项: (1). 编译器会对带有volatile关键字的... 当多个线程都要用到某一个变量且该变量的值会
4. Java多线程学习(三)volatile关键字 5. Java多线程学习(四)等待/通知(wait/notify)机制 6. Java多线程学习(五)线程间通信知识点补充 7. Java多线程学习(六)Lock锁的使用 8. Java多线程学习(七)...
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性。 2、C语言中struct和union的区别 在存储多个成员信息时,编译器会自动给struct第一个成员...
第三部分详细、深入地介绍volatile关键字的语义,volatile关键字在Java中非常重要,可以说它奠定了Java核心并发包的高效运行,在这一部分中,我们通过实例展示了如何使用volatile关键字以及非常详细地介绍了Java内存...
Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的线程 Java线程:新特征-锁(上) Java线程:新特征-锁(下) Java线程:新特征-信号量 Java线程:新特征-阻塞队列 Java线程:...
详细的讲述了多线程的各种用法 Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠...
您将了解线程安全的实现、死锁的避免策略、线程池的使用方法、线程上下文切换的原因与优化、线程同步与互斥的区别、volatile关键字的作用、synchronized关键字的用法等。同时,我们还探讨了多线程编程中 通过研究和...
volatile关键字可以保证变量的可见性,当一个线程修改了volatile变量的值,新值对于其他线程来说是立即可见的,这样可以防止由于线程间的数据不一致导致的问题 Lock接口 Lock接口提供了比synchronized关键字更广泛的...
Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制