15_volatile
【volatile概念】
volatile关键字的主要作用是是变量在多个线程间可见。
【注意】
在java中,每一个线程都会有一块工作内存区,其中存放着所有线程共享的主内存中的变量的拷贝。当线程执行时,他在自己的工作内存区中操作这些变量。为了存取一个共享的变量,一个线程通常会先获取并去清除它的内存工作区,把这些共享变量从所有线程的共享内存区中正确地装入到他自己所在的工作内存区中,当线程解锁时保证该内存区中变量的值写回到共享内存中。
一个线程可以执行的操作有:使用(use)、赋值(assign)、装载(load)、存储(store)、锁定(lock)、解锁(unlock)。
而主内存可以执行的操作有:读(read)、写(write)、锁定(lock)、解锁(unlock),每个操作都是原子的。
volatile的作用就是强制线程到主内存(共享内存)里去读取变量,而不去线程工作内存区里去读取,从而实现了多个线程间的变量可见。也就是满足线程安全的可见性。
【线程执行流程图】

【volatile可见性的例子】
package com.higgin.part6;
public class MyThread extends Thread{
/**
* 加与不加volatile
* 不加volatile:main线程中将isRunning设置为flase,MyThread线程中的isRunning不会改变
* 加上volatile:main线程中将isRunning设置为flase,MyThread线程中的isRunning会随之改变
*/
private volatile boolean isRunning = true;
private void setRunning(boolean isRunning){
this.isRunning = isRunning;
}
@Override
public void run(){
System.out.println("进入run()方法...");
while(isRunning){
//如果MyThread线程的isRunning不改为false,线程会永远卡在这里
}
System.out.println("线程停止!!!");
}
public static void main(String[] args) throws InterruptedException {
MyThread mt = new MyThread();
mt.start();
Thread.sleep();
mt.setRunning(false);
System.out.println("isRunning的值已经设置为false...");
}
}
【运行结果:不加volatile,MyThread线程一直没有结束】

【运行结果:加上volatile,Main线程改变了isRunning,MyThread线程中的isRunning随之改变,MyThread线程可以停止】

【volatile只有可见性,没有原子性的验证例子】
package com.higgin.part6; import java.util.concurrent.atomic.AtomicInteger; /**
* volatile关键字具备可见性,但不具备synchronized关键字的原子性(同步)
*/
public class VolatileThread extends Thread{ /**
* 使用volatile int 和 AtomicInteger的区别
* 使用volatile int :只有可见性,没有原子性
* 使用 AtomicInteger:原子性,确保最终的结果必为50000
*/
private static volatile int count;
// private static AtomicInteger count = new AtomicInteger(0); //初始化为0 private static void addCount(){
for(int i=; i<; i++){
count++;
// count.incrementAndGet();
}
System.out.println("count="+count); //for循环结束后,打印count的值
} @Override
public void run(){
addCount();
} public static void main(String[] args) {
VolatileThread[] threads = new VolatileThread[]; //100个线程 for(int i=; i<; i++){
threads[i] = new VolatileThread(); //为数组中的每个元素初始化对象
} for(int i=; i<; i++){
threads[i].start();
}
} }
【运行结果,使用volatile,多运行几遍会出现错误】

【运行结果:使用AtomicInteger】

【运行结果:使用AtomicInteger,虽然中间有可能会出现数据错乱的问题,但最终结果必定为50000】

【多个addAndGet在一个方法内是非原子性的,需要加synchronized修饰,保证4个addAndGet的原子性】
package com.higgin.part6; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; public class AtomicDemo {
private static AtomicInteger count = new AtomicInteger(); /**
* 加和不加synchronized
* 多个addAndGet在一个方法内是非原子性的,需要加synchronized修饰,保证4个addAndGet的原子性
*/
public synchronized int multiAdd(){
count.addAndGet();
count.addAndGet();
count.addAndGet();
count.addAndGet(); //count=count+1+2+3+4=count+10;
return count.get(); //返回count的值
} public static void main(String[] args) {
final AtomicDemo ad = new AtomicDemo(); List<Thread> tList = new ArrayList<Thread>(); for(int i=; i<; i++){
tList.add(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("count=="+ad.multiAdd());
}
}));
} for(Thread t : tList){
t.start();
}
}
}
【运行结果:不加synchronized,虽然可以确保最后一次结果为1000,但是中途有可能不是10的倍数】

【运行结果:加上synchronized修饰】

15_volatile的更多相关文章
随机推荐
- Qt 学习之路 2(32):贪吃蛇游戏(2)
Qt 学习之路 2(32):贪吃蛇游戏(2) 豆子 2012年12月27日 Qt 学习之路 2 55条评论 下面我们继续上一章的内容.在上一章中,我们已经完成了地图的设计,当然是相当简单的.在我们的游 ...
- day--39-MySQL的多表查询
多表查询一:表的基本介绍 可以参考:https://www.cnblogs.com/cdf-opensource-007/p/6517627.html 建立一个员工表信息表和一个部门表,每个员工都对应 ...
- css类选择器中 空格 逗号 啥都不填的区别及其他笔记
.a.b 代表 一个元素上 同时 有 a 类 和 b 类 .a .b (中间有空格) 代表 .b 是 .a 的子元素选择. .a,.b 代表 class='a' 和 class='b' 都会被选择上.
- mysql ibdata 单独存储
简介ibdata1 ibdata1文件是InnoDB存储引擎的共享表空间文件,存放位置my.ini 中的 datadir="D:\phpStudy\MySQL\data",目录下. ...
- Codeforces Round #462 (Div. 2), problem: (C) A Twisty Movement (求可以转一次区间的不递增子序列元素只有1,2)
题目意思: 给长度为n(n<=2000)的数字串,数字只能为1或者2,可以将其中一段区间[l,r]翻转,求翻转后的最长非递减子序列长度. 题解:求出1的前缀和,2的后缀和,以及区间[i,j]的最 ...
- apche 配置
http://www.tootoogo.org/wordpress/?p=230 apache的配置由httpd.conf 文件配置. 1.基本配置 ServerRoot "/mnt/sof ...
- [转] DOS命令for用法详解
[From] http://www.jb51.net/article/31284.htm for帮助文档 对一组文件中的每一个文件执行某个特定命令. FOR %variable IN (set) DO ...
- 51Nod - 1179
给出N个正整数,找出N个数两两之间最大公约数的最大值.例如:N = 4,4个数为:9 15 25 16,两两之间最大公约数的最大值是15同25的最大公约数5. Input第1行:一个数N,表示输入 ...
- 《STL详解》读书笔记
vector 向量容器v.insert(v.begin(), num);//增加v.erase(v.begin(), v.end()); //擦除v.erase(v.begin());reverse( ...
- AIDL(2):服务端回调客户端
1.大致流程 在服务端声明远程服务接口IRemoteService.aidl,并声明回调接口ICallback.aidl 在服务端实现远程服务接口IRemoteService.Stub 使用Remot ...