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 ...
随机推荐
- Java项目中读取properties文件,以及六种获取路径的方法
下面1-4的内容是网上收集的相关知识,总结来说,就是如下几个知识点: 最常用读取properties文件的方法 InputStream in = getClass().getResourceAsStr ...
- 2017国庆 清北学堂 北京综合强化班 Day1
期望得分:60+ +0=60+ 实际得分:30+56+0=86 时间规划极端不合理,T2忘了叉积计算,用解析几何算,还有的情况很难处理,浪费太多时间,最后gg 导致T3只剩50分钟,20分钟写完代码, ...
- HDP安全之集成kerberos/LDAP、ranger(knox自带LDAP)
----------------------目录导航见左上角------------------------------- 环境 HDP 3.0.1.0 (已有) JDK 1.8.0_91 (已有 ...
- JAVA中反射机制五(JavaBean的内省与BeanUtils库)
内省(Introspector) 是Java 语言对JavaBean类属性.事件的一种缺省处理方法. JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法 ...
- 推箱子 BFS
[编程题] 推箱子 大家一定玩过“推箱子”这个经典的游戏.具体规则就是在一个N*M的地图上,有1个玩家.1个箱子.1个目的地以及若干障碍,其余是空地.玩家可以往上下左右4个方向移动,但是不能移动出地图 ...
- Unity MMO 参考数值
贴图格式: iOS :RGBA 32 (pvrtc 4 ) Android : RGB Compresed ETC 4 或 RGBA 32 . DrawCall: 总计Drawcall 平均 100 ...
- 可能是是最全的Springboot基础视频分享,告别无视频可学
一头扎进SpringBoot视频教程 SpringBoot入门 2017年-张志君老师-SpringBoot(新增) 欢迎关注我的微信公众号:"Java面试通关手册" 回复关键字& ...
- arch安装完成之后不能使用笔记本自带的无线网卡
问题描述如下 我笔记本的wifi网卡识别不了,不知道为什么?? 使用ifconfig -a 只列出了有线网卡以及外接的无线网卡如下 enp4s0f1: flags=<UP,BROADCAST,M ...
- 【项目管理】git和码云的使用【转】
转自:https://www.cnblogs.com/riverdubu/p/6491944.html 缘起 说了那么多关于git和码云相关的事,一直都没给大伙讲解这个码云究竟是个啥玩意儿. 今天就给 ...
- PHP--- JSON和数组的转换
一.json_encode() <?php $arr =array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5); echo json_ ...