Java多线程编程——volatile关键字
(本篇主要内容摘自《Java多线程编程核心技术》)
volatile关键字的主要作用是保证线程之间变量的可见性。
package com.func;
public class RunThread extends Thread{
private boolean isRunning = true;
// volatile private boolean isRunning = true;
public boolean isRunning() {
return isRunning;
}
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
@Override
public void run(){
System.out.println("进入 run 了!");
while (isRunning == true) {
}
System.out.println("停止运行了!");
}
}
package com.test;
import com.func.RunThread;
public class Test3 {
public static void main(String[] args){
try {
RunThread runThread = new RunThread();
runThread.start();
Thread.sleep(1000);
runThread.setRunning(false);
System.out.println("isRunning已经赋值为false");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

将JVM设置为-server时就会出现下面状况

可以看到 System.out.println("停止运行了!"); 没有得到运行,也就是说isRunning 一直是true的状态。 runThread.setRunning(false); 这句话并没有起到相应的作用。
那么为什么会这样呢?
原因就在于私有堆栈和公共堆栈中的值不一致造成的。当把JVM设置成-server的方式,为了执行效率,线程会一直在私有堆栈中取值。 runThread.setRunning(false);将公共堆栈中的isRunning设置成为false,但是私有堆栈中的isRunning 并没有得到同步。
面对这种情况就可以采用volatile关键字解决。将isRunniing变量使用volatile关键字修饰。
volatile private boolean isRunning = true;
volatile关键字强制线程从公共堆栈中获取变量值,而不是从私有堆栈中获取变量值。
使用volatile关键字可以增加实力变量在多个线程之间的可见性。但是volatile关键字只是保证可见性并不保证原子性。不能使用volatile关键字来保证线程安全。
下面的例子会说明volatile关键字不能保证线程安全。
package com.func;
public class MyThread extends Thread{
volatile public static int count;
// public static int count;
private static void addCount(){
// synchronized private static void addCount(){
for (int i = 0; i < 100; i++) {
count ++;
}
System.out.println("count = " + count);
}
@Override
public void run(){
addCount();
}
}
package com.test;
import com.func.MyThread;
public class Test {
public static void main(String[] args){
try {
MyThread[] myThreads = new MyThread[100];
for (int i = 0; i < 100; i++) {
myThreads[i] = new MyThread();
}
for (int i = 0; i < myThreads.length; i++) {
myThreads[i].start();
}
} catch (Exception e) {
// TODO: handle exception
}
}
}

可以看见最后的结果并不是10000,看见volatile并不能保证线程安全。虽然数据都是从公共堆栈取出来的,但是数据的取出来之后的修改并不是原子操作(count++这样的操作并不是原子的),所以最后将修改后的数据进行同步时,数据并不是我们想要的。
为了保证数据的原子性,我们还是需要使用synchronized关键字。synchronized关键字保证了原子性,解决了多个线程之间访问资源的同步性。
synchronized private static void addCount(){
...
}
Java多线程编程——volatile关键字的更多相关文章
- Java并发编程 Volatile关键字解析
volatile关键字的两层语义 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了 ...
- Java多线程:volatile 关键字
一.内存模型的相关概念 大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存 ...
- 【java多线程】volatile 关键字
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
- Java并发编程volatile关键字
volatile理解 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和volatile 关键字机制.volatile具有synchronized关键字的“可见性”,vo ...
- Java多线程技术-Volatile关键字解析
分析volatile关键字可以从这三个方面分析,什么是程序的原子性,什么是程序的可见性,什么是程序的有序性 什么是程序的原子性 以下语句那些是原子操作? public class ThreadCoun ...
- java并发编程 volatile关键字 精准理解
1.volatile的作用 一个线程共享变量(类的成员变量.类的静态成员变量等)被volatile修饰之后,就具有以下作用: 1)并发中的变量可见性(不同线程对该变量进行操作时的可见性),即一个线程修 ...
- Java多线程编程那些事:volatile解惑--转
http://www.infoq.com/cn/articles/java-multi-thread-volatile/ 1. 前言 volatile关键字可能是Java开发人员“熟悉而又陌生”的一个 ...
- java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)
概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...
- Java多线程编程核心技术---学习分享
继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...
随机推荐
- ZOJ 3787 Access System 水
LINK:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3787 思路:结构体 时间转化为秒记录下最小并且排序就好了 /** ...
- CSS进阶知识
html { -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } 该属性的作用是 ...
- Shiro实战教程(二)
http://www.jianshu.com/p/6786ddf54582/ https://www.cnblogs.com/ealenxie/p/10610741.html
- 56、isinstance作用以及应用场景?
isinstance作用:来判断一个对象是否是一个已知的类型: 其第一个参数(object)为对象,第二个参数为类型名(int...)或类型名的一个列表((int,list,float)是一个列表). ...
- Class类和ClassLoader类的简单介绍
反射机制中的Class Class内部到底有什么呢?看下图! 代码: Class cls=Person.class; 1.Class类: 1. 对象照镜子后可以得到的信息:某个类的数据成员名,方法和构 ...
- weblogic 开启注意问题
1.关闭防火墙 service iptables stop chkconfig iptables off 2.weblogic unable to get file lock问题 我的解决办法是ps ...
- python进阶之内置函数和语法糖触发魔法方法
前言 前面已经总结了关键字.运算符与魔法方法的对应关系,下面总结python内置函数对应的魔法方法. 魔法方法 数学计算 abs(args):返回绝对值,调用__abs__; round(args): ...
- atoll()函数使用注意事项及分析
atoll是c99标准加入的函数,在编译的时候可能要打开C99标准的编译选项 -std=c99. 另外,必须包含stdlib.h头文件,否则会出错. ☞ C程序代码如下所示: #include < ...
- slave->pxc后GTID不一致
以下两个参数在两个节点是对得上的. | wsrep_last_applied | 3363764 | | wsrep_last_committed | 3363764 但show master sta ...
- ButterKnifeZelezny简单使用教程
https://github.com/avast/android-butterknife-zelezny 一,配置butterknife Configure your project-leve ...