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的更多相关文章
随机推荐
- su切换用户报错cannot set user id: Resource temporarily unavailable
su: cannot set user id: 资源暂时不可用 登录root su - tomcat 报错: cannot set user id: Resource temporarily un ...
- python基础01—基础数据类型
数据类型 单位换算 最小的单位为bit,表示一个二进制的0或1,一般使用小写的b表示 存储的最小单位为字节(Byte),1B = 8b 1024B = 1KB 1024KB = 1MB 1024MB ...
- JavaWeb学习笔记(六)—— Cookie&Session
一.会话技术简介 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程 ...
- Android TextUtils工具类的使用
1.采用File类,在指定目录下读写数据 java后台代码为: (1)向app的/data/data/com.example.lucky.helloworld目录下写入文本(涉及IO的读写操作) pa ...
- Kibana源码分析--Hapijs路由设置理解笔记
[ES6解构赋值]:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_ ...
- [一首诗] Life and Death 生与死
Life and Death 生与死 I strove with none, 我和谁都不争, for none was worth my strife, 和谁争我都不屑: Nature I loved ...
- 一些英文表达-youtube
culinary tradition 烹饪传统 crunchy 松脆的 boutique 精品店 migraine 偏头痛 colon 冒号 towel 毛巾 ecstatic 狂喜的 bok ...
- CodeForces 1043D Mysterious Crime 区间合并
题目传送门 题目大意: 给出m个1-n的全排列,问这m个全排列中有几个公共子串. 思路: 首先单个的数字先计算到答案中,有n个. 然后考虑多个数字,如果有两个数字相邻,那么在m个串中必定都能找到这两个 ...
- 使用Maven运行Java main的3种方式使用Maven运行Java main的3种方式
maven使用exec插件运行java main方法,以下是3种不同的操作方式. 一.从命令行运行 1.运行前先编译代码,exec:java不会自动编译代码,你需要手动执行mvn compile来完成 ...
- <?>与<T>的区别
?是通配符(占位符),可以表示任意一个,T只是一种替代,只能表示其中一个 假设有A,B,C三个类 <?>可以是A,B,C任意一个,每一个<?>之间没有关联 <T>如 ...