1.解决并发编程中的可见性问题

volatile 代表不使用cpu缓存,修改后的数据,将直接刷到内存中,被volatile修饰的变量,读取的时候,也是从内存中读取,不从cpu缓存中读取

上代码


// 以下代码来源于【参考1】
class VolatileExample {
int x = 0;
volatile boolean v = false;
public void writer() {
x = 42;
v = true;
}
public void reader() {
if (v == true) {
// 这里x会是多少呢?
}
}
}

例如上面的示例代码,

假设线程 A 执行 writer() 方法,按照 volatile 语义,会把变量 “v=true” 写入内存;

假设线程 B 执行 reader() 方法,同样按照 volatile 语义,线程 B 会从内存中读取变量 v,如果线程 B 看到 “v == true” 时,那么线程 B 看到的变量 x 是多少呢?

直觉上看,应该是 42,那实际应该是多少呢?这个要看 Java 的版本,如果在低于 1.5 版本上运行,x 可能是 42,也有可能是 0;如果在 1.5 以上的版本上运行,x 就是等于 42。

为什么呢?

  • 变量 x 可能被 CPU 缓存而导致可见性问题。这个问题在 1.5 版本已经被圆满解决了。Java 内存模型在 1.5 版本对 volatile 语义进行了增强。怎么增强的呢?答案是一项 Happens-Before 规则。

这个规则就是:

前面一个操作的结果对后续操作是可见的

2.六项Happens-Before规则

1. 程序的顺序性规则

这条规则是指在一个线程中,按照程序顺序,前面的操作 Happens-Before 于后续的任意操作。这还是比较容易理解的,比如刚才那段示例代码,按照程序的顺序,第 6 行代码 “x = 42;” Happens-Before 于第 7 行代码 “v = true;”,这就是规则 1 的内容,也比较符合单线程里面的思维:程序前面对某个变量的修改一定是对后续操作可见的。

2. volatile 变量规则

对一个 volatile 变量的写操作, Happens-Before 于后续对这个 volatile 变量的读操作。

3.传递性

这条规则是指如果 A Happens-Before B,且 B Happens-Before C,那么 A Happens-Before C。

对应到上面的源码中就是

x=42 Happens-Before 写变量v=true 对应规则(程序的顺序性规则)

写变量v=true Happens-Before 读变量if(v==true) 对应规则2(volatile变量规则)

4.管程中的锁规则

管程,就是同步愿语,java中指的就是synchronized

上代码


synchronized (this) { //此处自动加锁
// x是共享变量,初始值=10
if (this.x < 12) {
this.x = 12;
}
} //此处自动解锁

假设 x 的初始值是 10,线程 A 执行完代码块后 x 的值会变成 12(执行完自动释放锁),线程 B 进入代码块时,能够看到线程 A 对 x 的写操作,也就是线程 B 能够看到 x==12

5.start()规则

主线程 A 启动子线程 B 后,子线程 B 能够看到主线程在启动子线程 B 前的操作。

上代码


Thread B = new Thread(()->{
// 主线程调用B.start()之前
// 所有对共享变量的修改,此处皆可见
// 此例中,var==77
});
// 此处对共享变量var修改
var = 77;
// 主线程启动子线程
B.start();

6.join()规则

如果在线程 A 中,调用线程 B 的 join() 并成功返回,那么线程 B 中的任意操作 Happens-Before 于该 join() 操作的返回

3.Java 内存模型

Java 内存模型规范了 JVM 如何提供按需禁用缓存和编译优化的方法

具体来说,这些方法包括 volatile、synchronized 和 final 三个关键字,以及六项 Happens-Before 规则

Volatile 原理及使用,java并发中的可见性问题的更多相关文章

  1. 深入浅出Java并发中的CountDownLatch

      1. CountDownLatch 正如每个Java文档所描述的那样,CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行.在Java并发中 ...

  2. java并发中CountDownLatch的使用

    文章目录 主线程等待子线程全都结束之后再开始运行 等待所有线程都准备好再一起执行 停止CountdownLatch的await java并发中CountDownLatch的使用 在java并发中,控制 ...

  3. java并发中ExecutorService的使用

    文章目录 创建ExecutorService 为ExecutorService分配Tasks 关闭ExecutorService Future ScheduledExecutorService Exe ...

  4. java并发中的Synchronized关键词

    文章目录 为什么要同步 Synchronized关键词 Synchronized Instance Methods Synchronized Static Methods Synchronized B ...

  5. Java并发编程-线程可见性&线程封闭&指令重排序

    一.指令重排序 例子如下: public class Visibility1 { public static boolean ready; public static int number; } pu ...

  6. 一起来看看java并发中volatile关键字的神奇之处

    并发编程中的三个概念: 1.原子性 在Java中,对基本数据类型的变量的读取和赋值操作是原子性操作,即这些操作是不可被中断的,要么执行,要么不执行. 2.可见性 对于可见性,Java提供了volati ...

  7. Java并发中的CopyOnWrite容器

    Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...

  8. Generate PDF in Sourcing through concurrent request,在EBS java并发中调用指定am的方法

    package oracle.apps.pon.printing.cp; import java.io.InputStream; import java.io.FileOutputStream; im ...

  9. java并发中的锁

    java中的锁,最基本的是Lock接口. Lock接口中的方法,主要是: lock(): 获取锁,lock()方法会对Lock实例对象进行加锁,因此所有对该对象调用lock()方法的线程都会被阻塞,直 ...

随机推荐

  1. ASP程序写的项目与微信服务号(公众号)完美结合。仅需一个DLL组建WeixinDLL

    因ASP程序开发有很多优点,早年间ASP风靡全球,因此如今还在继续运营的ASP开发的项目仍在运行着,但是随着社交网络不断发达,特别是微信支付.微信通讯.小程序等的出现,导致很多ASP项目对接起来就比较 ...

  2. SSL证书及HTTPS服务器

    1. 域名 在万网购买,略 2. 云服务器 阿里云购买,略 3. 安装lnmp 使用lnmp.org程序,略 4. 申请证书 阿里云-管理控制台-安全(云盾)-证书服务-购买证书证书类型: 免费型DV ...

  3. hdu3472 混合欧拉

    题意:       给你一些字符串,有的字符串反过来也有意义,题目问给的这n个字符串是否可以首尾相连,组成一个串. 思路:       算是混合欧拉的基础题目了,混合欧拉就是专门处理这类问题的,先说下 ...

  4. Win64 驱动内核编程-11.回调监控进线程句柄操作

    无HOOK监控进线程句柄操作 在 NT5 平台下,要监控进线程句柄的操作. 通常要挂钩三个API:NtOpenProcess.NtOpenThread.NtDuplicateObject.但是在 VI ...

  5. Thyemleaf报错: Method call: Attempted to call method *** on null context object

    翻译:方法调用:尝试在null上下文对象上调用方法*** 解释:在Thyemleaf上下中不存在所要调用的对象,相当于Java代码中的NullPointerException 解决方案: 方案1. 需 ...

  6. 支付宝手机端网页支付 PHP(基于官方提供的demo)

    1.支付宝开放平台添加应用并且签约快捷手机wap支付(应用添加不做详细说明) 2.下载demo,文档中心SDK&Demo, 3.个人中心秘钥管理,查看商户appID,商户私钥,支付宝公钥,商户 ...

  7. vuex、localStorage、sessionStorage之间的区别

    vuex存储在内存中,localStorage以文件形式存储在本地,sessionStorage针对一个session(阶段)进行数据存储. 当页面刷新时vuex存储的数据会被清除,localStor ...

  8. VS2010编写32位和64位dll环境配置,以及判断dll是多少位

    前言 最近在编写dll注入程序的时候,因为想注入到系统进程,结果发现总是注入失败.自闭了好长一会发现我忘记了我的系统是64位的,系统进程也是64位的,而我编写的待注入的DLL是32位了,所以才导致失败 ...

  9. MySQL查看及杀掉链接方法大全

    前言: 在数据库运维过程中,我们时常会关注数据库的链接情况,比如总共有多少链接.有多少活跃链接.有没有执行时间过长的链接等.数据库的各种异常也能通过链接情况间接反应出来,特别是数据库出现死锁或严重卡顿 ...

  10. .Net Core导入千万级数据至Mysql

    ​最近在工作中,涉及到一个数据迁移功能,从一个txt文本文件导入到MySQL功能. 数据迁移,在互联网企业可以说经常碰到,而且涉及到千万级.亿级的数据量是很常见的.大数据量迁移,这里面就涉及到一个问题 ...