volatile修饰全局变量,可以保证并发安全吗?
今天被人问到volatile能不能保证并发安全?
呵,这能难倒我?
上代码:
//电脑太好,100线程起步~
public class ThreadTest {
private static volatile int num = 0; public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); Thread.sleep(500);
System.out.println(num);
}
}
输出结果:
9998
9998
分析:
100个线程对volatilei修饰的num++,会被编译成以下三步:
1.获取i的值;2.执行i+1;3.将结果赋值给i。
volatile只能保证可见性,并不能保证原子性。
结论:
volatile只能保证这3步在编译后指令不会被重新排序,并不能保证并发数据安全。建议搭配上synchronized或其他Lock锁使用。
volatile修饰全局变量,可以保证并发安全吗?的更多相关文章
- volatile修饰符
Volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值.而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存.这样在任何时刻,两个不同的线程总是看到某个成 ...
- Java 的 volatile 修饰符
volatile 修饰符,用于多线程同步 volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值.而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存.这 ...
- Java中volatile修饰符,不稳定标记的用法笔记
今天学java特性时,发现了volatile修饰符,这个修饰符修饰的变量告诉java编译器忽略优化机制,这样的优势是: java优化后,寄存器会缓存内存里的变量,另一个线程修改这个变量的内存时,不会同 ...
- java中Volatile修饰符的含义
在java语言中:为了获得最佳速度,同意线程保存共享成员变量的私有拷贝.并且仅仅当线程进入或者离开同步代码块时才与共享成员变量的原始值进行对照. volatilekeyword的作用就是提示vm:对于 ...
- Java volatile修饰字段
一.关键字volatile修饰字段: 使用特殊域变量(volatile)实现线程同步 volatile:不稳定的:反复无常的:易挥发的: 1.volatile关键字为域变量的访问提供了一种免锁机制, ...
- volatile 修饰符的有过什么实践?
一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写. double 和 long 都是 64 位宽,因此对这两种类型的读是分为两部分的,第一次 读取第一个 ...
- 三个线程,ABC 10次(volatile+synchronized(2 synchronized可以保证内存可见性,所以去掉status 的volatile修饰符)
package ThreadABC; public class MyThread extends Thread { public static int status = 0; @Override pu ...
- 关于STM32库中 __IO 修饰符(volatile修饰符,反复无常的意思)
STM32例子代码中会有像这样的代码 static __IO uint32_t TimingDelay; 这里边的__IO修饰符不好理解,单从字面可以看出是为IO相关,查其标准库可以得知这个__IO ...
- STM32库中 __IO 修饰符(volatile修饰符)
STM32例子代码中会有像这样的代码 static __IO uint32_t TimingDelay; 这里边的__IO修饰符不好理解,单从字面可以看出是为IO相关,查其标准库可以得知这个__IO原 ...
随机推荐
- C++对象的生存期笔记
下面随笔记录了C++对象的生存期知识 静态生存期 这种生存期与程序的运行期相同. 在文件作用域中声明的对象具有这种生存期. 在函数内部声明静态生存期对象,要冠以关键字static . 动态生存期 块作 ...
- 精确率precession和召回率recall
假设有两类样本,A类和B类,我们要衡量分类器分类A的能力. 现在将所有样本输入分类器,分类器从中返回了一堆它认为属于A类的样本. 召回率:分类器认为属于A类的样本里,真正是A类的样本数,占样本集中所有 ...
- 十一. SpringCloud Alibaba
1. SpringCloud Alibaba简介 1.1 为什么会出现SpringCloud Alibaba Spring Cloud Netflix项目进入到维护模式 什么是维护模式?=> 将 ...
- golang——net/rpc包学习
1.rpc包 rpc包提供了通过网络或其他I/O连接对一个对象的导出方法的访问. 只有满足如下标准的方法才能用于远程访问,其余方法会被忽略: (1)方法是导出的(2)方法有两个参数,都是导出类型或内建 ...
- TiDB在更新版本的时候初始化Prometheus的配置文件失败
一.背景是更换版本了之后,按照正常扩容节点也会报错. 我们安装的TiDB版本是v4.0.0,因为环境还在试用阶段,所以会经常增删节点.原因是我们违背官方说明,强行用机械盘上了,跑不过单机的mysql, ...
- 对话对话每日互动CEO方毅:数据智能应用的过去、现在和未来每日互动CEO方毅:数据智能应用的过去、现在和未来
2008年,大数据的概念被首次提出,麦肯锡全球研究所给出的定义是:大数据是在一种获取.存储.管理.分析方面大大超出了传统数据库软件工具能力范围的数据集合. 2014年,"数据智能" ...
- 「NOIP模拟赛」Round 3
Tag 计数+LIS, 二分+ST表, 计数+记搜 A. 改造二叉树 Description 题面 Solution 如果目标序列非严格递增,或者说目标序列是不下降的,那么答案就是 \(n\) 减去最 ...
- css整理之-----------技巧、黑魔法
css 看起来比较简单,但是要想做的好也不是那么容易,我们在平时开发中,主要用css 来美化我们的html结构,所有我觉得css 还是挺重要的,这里记录整理一些关于css 的技巧以及容易忘记的知识点. ...
- python打印9宫格25宫格81宫格.....
""" 2 问题描述: 3 给定一个奇数(num),生成一个横竖斜加起来的和相等 4 问题解析: 5 这其实就是一个九宫格的问题 6 九宫格问题的解答技巧: 7 1要放在 ...
- 解决linux sudo apt-get install xx是2出现无法定位软件包方法
解决办法: 在etc/apt/sources.list最后一行添加 deb http://archive.ubuntu.com/ubuntu/ trusty main universe restric ...