| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 8大原则带你秒懂Happens-Before原则 -> 正文阅读 |
|
[Java知识库]8大原则带你秒懂Happens-Before原则 |
摘要:在并发编程中,Happens-Before原则是我们必须要掌握的,今天我们就一起来详细聊聊并发编程中的Happens-Before原则。 本文分享自华为云社区《【高并发】一文秒懂Happens-Before原则》,作者:冰 河。 在并发编程中,Happens-Before原则是我们必须要掌握的,今天我们就一起来详细聊聊并发编程中的Happens-Before原则。 在正式介绍Happens-Before原则之前,我们先来看一段代码。 【示例一】
以上示例来源于:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalWrong 这里,假设线程A执行writer()方法,按照volatile会将v=true写入内存;线程B执行reader()方法,按照volatile,线程B会从内存中读取变量v,如果线程B读取到的变量v为true,那么,此时的变量x的值是多少呢?? 这个示例程序给人的直觉就是x的值为42,其实,x的值具体是多少和JDK的版本有关,如果使用的JDK版本低于1.5,则x的值可能为42,也可能为0。如果使用1.5及1.5以上版本的JDK,则x的值就是42。 看到这个,就会有人提出问题了?这是为什么呢?其实,答案就是在JDK1.5版本中的Java内存模型中引入了Happens-Before原则。 接下来,我们就结合案例程序来说明Java内存模型中的Happens-Before原则。 【原则一】程序次序规则在一个线程中,按照代码的顺序,前面的操作Happens-Before于后面的任意操作。 例如【示例一】中的程序x=42会在v=true之前执行。这个规则比较符合单线程的思维:在同一个线程中,程序在前面对某个变量的修改一定是对后续操作可见的。 【原则二】volatile变量规则对一个volatile变量的写操作,Happens-Before于后续对这个变量的读操作。 也就是说,对一个使用了volatile变量的写操作,先行发生于后面对这个变量的读操作。这个需要大家重点理解。 【原则三】传递规则如果A Happens-Before B,并且B Happens-Before C,则A Happens-Before C。 我们结合【原则一】、【原则二】和【原则三】再来看【示例一】程序,此时,我们可以得出如下结论: (1)x = 42 Happens-Before 写变量v = true,符合【原则一】程序次序规则。 (2)写变量v = true Happens-Before 读变量v = true,符合【原则二】volatile变量规则。 再根据【原则三】传递规则,我们可以得出结论:x = 42 Happens-Before 读变量v=true。 也就是说,如果线程B读取到了v=true,那么,线程A设置的x = 42对线程B就是可见的。换句话说,就是此时的线程B能够访问到x=42。 其实,Java 1.5版本的 java.util.concurrent并发工具就是靠volatile语义来实现可见性的。 【原则四】锁定规则对一个锁的解锁操作 Happens-Before于后续对这个锁的加锁操作。 例如,下面的代码,在进入synchronized代码块之前,会自动加锁,在代码块执行完毕后,会自动释放锁。 【示例二】
我们可以这样理解这段程序:假设变量x的值为10,线程A执行完synchronized代码块之后将x变量的值修改为10,并释放synchronized锁。当线程B进入synchronized代码块时,能够获取到线程A对x变量的写操作,也就是说,线程B访问到的x变量的值为10。 【原则五】线程启动规则如果线程A调用线程B的start()方法来启动线程B,则start()操作Happens-Before于线程B中的任意操作。 我们也可以这样理解线程启动规则:线程A启动线程B之后,线程B能够看到线程A在启动线程B之前的操作。 我们来看下面的代码。 【示例三】
上述代码是在线程A中执行的一个代码片段,根据【原则五】线程的启动规则,线程A启动线程B之后,线程B能够看到线程A在启动线程B之前的操作,在线程B中访问到的x变量的值为100。 【原则六】线程终结规则线程A等待线程B完成(在线程A中调用线程B的join()方法实现),当线程B完成后(线程A调用线程B的join()方法返回),则线程A能够访问到线程B对共享变量的操作。 例如,在线程A中进行的如下操作。 【示例四】
【原则七】线程中断规则对线程interrupt()方法的调用Happens-Before于被中断线程的代码检测到中断事件的发生。 例如,下面的程序代码。在线程A中中断线程B之前,将共享变量x的值修改为100,则当线程B检测到中断事件时,访问到的x变量的值为100。 【示例五】
【原则八】对象终结原则一个对象的初始化完成Happens-Before于它的finalize()方法的开始。 例如,下面的程序代码。 【示例六】
运行结果如下所示。
好了,今天就到这儿吧。我们下期见~~ |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 2:06:27- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |