用 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的更多相关文章

  1. volatile和synchronized到底啥区别?多图文讲解告诉你

    你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...

  2. java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解

    一.JMM(java memory model)内存模型 从网上淘来二张图: 上面这张图说的是,在多核CPU的系统中,每个核CPU自带高速缓存,然后计算机主板上也有一块内存-称为主内(即:内存条).工 ...

  3. 理解volatile

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  4. 剑指Offer——线程同步volatile与synchronized详解

    (转)Java面试--线程同步volatile与synchronized详解 0. 前言 面试时很可能遇到这样一个问题:使用volatile修饰int型变量i,多个线程同时进行i++操作,这样可以实现 ...

  5. Java并发专题(三)深入理解volatile关键字

    前言 上一章节简单介绍了线程安全以及最基础的保证线程安全的方法,建议大家手敲代码去体会.这一章会提到volatile关键字,虽然看起来很简单,但是想彻底搞清楚需要具备JMM.CPU缓存模型的知识.不要 ...

  6. java多线程中 volatile与synchronized的区别-阿里面试

    volatile 与 synchronized 的比较(阿里面试官问的问题) ①volatile轻量级,只能修饰变量.synchronized重量级,还可修饰方法 ②volatile只能保证数据的可见 ...

  7. volatile和synchronized实现内存可见性的区别

    先看看synchronized实现内存可见性 加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另外一个重要的方面:内存可见性.我们不仅希望防止某个线程正在使用对象状态而另一个 ...

  8. volatile和synchronized的区别

    volatile和synchronized特点 首先需要理解线程安全的两个方面:执行控制和内存可见. 执行控制的目的是控制代码执行(顺序)及是否可以并发执行. 内存可见控制的是线程执行结果在内存中对其 ...

  9. JAVA多线程之volatile 与 synchronized 的比较

    一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...

随机推荐

  1. WinForm皮肤 支持.NET4.0 IrisSkin4多彩皮肤演示和下载

    IrisSkin4是一款.NET平台非常优秀的Winform皮肤,链接库文件仅544kb,使用方法也非常简单 IrisSkin4(IrisSkin4.dll + 73套皮肤)[下载地址] 使用方法: ...

  2. 管理员账户权限不足 解决方案 类似没有XXX权限之类的问题解决方法

  3. java并发编程 volatile关键字 精准理解

    1.volatile的作用 一个线程共享变量(类的成员变量.类的静态成员变量等)被volatile修饰之后,就具有以下作用: 1)并发中的变量可见性(不同线程对该变量进行操作时的可见性),即一个线程修 ...

  4. 微信小程序入门开发文档

    第一步:下载微信小程序开发者工具并安装,下载路径: https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html 进到下载界面后,根 ...

  5. Android内存监测工具使用

    用 Heap监测应用进程使用内存情况的步骤如下:1. 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的:2. 将手机通过USB链接至电脑,链接时需要确认手机 ...

  6. 腾讯bugly 映射用法

    package com.tencent.bugly.agent; import android.app.Activity; import android.content.Context; import ...

  7. python模块详解 shelve

    shelve模块是一个简单的k,v 将内存数据通过文件持久化的模块,可以持久化任何pickle可以支持的python数据.简单的说对 pickle的更上一层的封装. 写文件 import shelve ...

  8. C#多线程Thread

    在项目中经常用到线程Thread,先做个简单记录,后面再完善下,方便以后参考.本人技术有限,如有不同见解之处,欢迎博友批评指正. 执行的线程Thread分无参数的,一个参数,多个参数的.直接看代码吧. ...

  9. 解压war包

    unzip cat-alpha-3.0.0.war -d /tmp/test 说明:-d指定解压的路径和文件,文件名不存在会自动创建

  10. Canvas 中drawImage 绘制不出图片

    在使用Canvas的drawImage绘制图片时,却发现绘制不出图片,原因是图片是异步加载,图片加载完再绘制. //html <img src="1.png" /> & ...