理解volatile与synchronized
用 volatile 修饰的变量可以保证线程的“可见性”,也就是,任何线程修改了这个 volatile 修饰的值都会通知其他线程来主缓存中重新读取值。
下面通过例子加以说明:
public class VolatileTest {
// 对比有无 volatile 关键字的区别
volatile boolean running = true;
public void m(){
System.out.println("start run");
while (running){
}
System.out.println("end run");
}
public static void main(String[] args) {
VolatileTest volatileTest = new VolatileTest();
new Thread(volatileTest::m, "t1").start();
try {
//主线程睡眠一秒钟,目的是保证t1获得cpu执行权
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
volatileTest.running = false;
}
}
有volatile的情况下,程序会输出:
start run
end run
无volatile的情况下,程序会输出:
start run
出现这种情况的原因跟java的内存模型(JMM)有关,每个线程运行都有自己独立的一份内存,用于保存线程的局部变量,线程修改一个全局变量要经过三个过程:
i. 拷贝主内存的变量到线程内存。
ii. 修改拷贝的变量值。
iii. 把修改的值写回主内存。
由于线程修改一个公共变量需要这三个步骤,可见这个修改不具备“原子性”,这也就是volatile和synchronized的不同之处,volatile不能取代synchronized来使用。
如下面例子所示:
public class VolatleAndSynchornized {
public volatile int count = 0;
// public synchronized void incre(){
public void incre(){
for (int i = 0; i < 10000; i ++){
count ++;
}
}
public static void main(String[] args) {
VolatleAndSynchornized obj = new VolatleAndSynchornized();
obj.process();
System.out.println(obj.count);
}
public void process() {
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 5; i ++) {
try {
Runner t = new Runner();
threads.add(t);
} catch (Exception e) {
e.printStackTrace();
}
}
threads.forEach(Thread::start);
threads.forEach(thread -> {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
public class Runner extends Thread {
@Override
public void run() {
incre();
}
}
}
用volatile的话输出:(每次运行结果不见得相同)
24236
而用synchronized的话输出:
50000
理解volatile与synchronized的更多相关文章
- volatile和synchronized到底啥区别?多图文讲解告诉你
你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...
- java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解
一.JMM(java memory model)内存模型 从网上淘来二张图: 上面这张图说的是,在多核CPU的系统中,每个核CPU自带高速缓存,然后计算机主板上也有一块内存-称为主内(即:内存条).工 ...
- 理解volatile
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- 剑指Offer——线程同步volatile与synchronized详解
(转)Java面试--线程同步volatile与synchronized详解 0. 前言 面试时很可能遇到这样一个问题:使用volatile修饰int型变量i,多个线程同时进行i++操作,这样可以实现 ...
- Java并发专题(三)深入理解volatile关键字
前言 上一章节简单介绍了线程安全以及最基础的保证线程安全的方法,建议大家手敲代码去体会.这一章会提到volatile关键字,虽然看起来很简单,但是想彻底搞清楚需要具备JMM.CPU缓存模型的知识.不要 ...
- java多线程中 volatile与synchronized的区别-阿里面试
volatile 与 synchronized 的比较(阿里面试官问的问题) ①volatile轻量级,只能修饰变量.synchronized重量级,还可修饰方法 ②volatile只能保证数据的可见 ...
- volatile和synchronized实现内存可见性的区别
先看看synchronized实现内存可见性 加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另外一个重要的方面:内存可见性.我们不仅希望防止某个线程正在使用对象状态而另一个 ...
- volatile和synchronized的区别
volatile和synchronized特点 首先需要理解线程安全的两个方面:执行控制和内存可见. 执行控制的目的是控制代码执行(顺序)及是否可以并发执行. 内存可见控制的是线程执行结果在内存中对其 ...
- JAVA多线程之volatile 与 synchronized 的比较
一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...
随机推荐
- Unity3d开发集成Google Admob广告增加收入
在Unity游戏中植入广告是Unity 游戏产品增加收入的一种重要方式,常用的广告有谷歌Admob,百度ssp,腾讯广点通,unity公司的unityads等等,而使用的最多的应该属于谷歌Admob, ...
- html5 chrome 摄像头 &&bootstrap
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- Struts2_带参数的结果集
页面请求: <a href="user/user?type=1">传参数</a> action: public Integer type; public S ...
- 然之协同系统3.5(OA+CRM+CASH+TEAM)
平台: Ubuntu 类型: 虚拟机镜像 软件包: mariadb-server 10.0.25 nginx 1.10.0 php7.0.4 collaboration commercial crm ...
- 建堆复杂度O(n)证明
堆排序中首先需要做的就是建堆,广为人知的是建堆复杂度才O(n),它的证明过程涉及到高等数学中的级数或者概率论,不过证明整体来讲是比较易懂的. 堆排过程 代码如下 void print(vector&l ...
- c++的bind1st()与bind2nd() 二元算子转一元算子
bind1st()和bind2nd()是两个函数,用于将二元算子转成一元算子. 何谓二元算子? 比如< > =等等这些就是二元算子,即需要两个操作数的运算符. 何谓一元算子? 比如++ - ...
- Linux Mint,Ubuntu 18 ,Deepin15.7 安装mysql 没有提示输入密码,修改root用户密码过程
刚刚装Deepin15.7 和 MySQL5.7 发现没有提示用户输入密码的过程(近日发现Linux Mint 和 Ubuntu18 也适用) 百度了一大堆如何修改root密码 也没什么卵用,终于这篇 ...
- Xapian简明教程(未完成)
第一章 简介 1.1 简介 Xapian是一个开源的搜索引擎库,它可以让开发者自定义的开发一些高级的的索引和查找因素应用在他们的应用中. 通过阅读这篇文档,希望可以帮助你创建第一个你的索引数据库和了解 ...
- QT学习之QString的arg方法
在QT的QString中,arg方法类似于C中的printf中使用的格式输出符(只是有点类似). 在QT5的帮助文档中,可以看出以下几点: 使用arg(str1, str2, str3)这种方法进行替 ...
- java 使用hashmap一个键对应多值的方法
背景:在你使用map对象时,你可能会有一个key,对应多个值的需求 实现: import java.util.ArrayList; import java.util.HashMap; import j ...