Java Happens-Before原则
Java Happens-Before原则
Happens-Before原则核心就是表达在一些条件下,前面的操作对于后面的操作是可见的。它有六个条件,或者说是六条原则。
一、线程中的顺序性原则
这个最容易理解,这个原则是指在同一个线程中,按照程序的顺序,前面的操作Happens-Before后面的操作。也就说在同一个线程中,前面先修改的数据,对于后面的操作是可见的。下面举例说明:
int a = 1;
if(a == 1){
}
上面代码中第一行对变量a进行的修改Happens-Before第二行查询a的操作,所以第二行a == 1
为true
。
二、volatile变量原则
这个原则是指在对于用volatile
修饰的变量,它的写操作Happens-Before后续对它的读操作。这个原则就是说在一个线程中先对volatile
变量进行了修改后,在另一个线程中读取该volatile
变量能够读到新值(因为CPU缓存的存在,可能在一个线程中修改了普通变量,另一个线程无法感知)。当然如果在同一个线程中,就可以直接使用原则一了。
volatile int a = 1;
// 线程A
a = 2;
// 线程B
if(a == 2){
}
上面代码中,假设有两个线程并发执行,线程A先对a进行赋值操作(第四行),然后线程B立刻读取a(第七行),此时能够保证读取的a一定是2。
三、传递性
这个原则是指Happens-Before原则是可以传递的,指如果A Happens-Before B,且B Happens-Before C,那么A Happens-Before C。
volatile boolean a = false;
int b = 1;
// 线程A
b = 2;
a = true;
// 线程B
if(a){
System.out.println(b);
}
上面代码中,线程A先对b进行赋值,然后对a进行赋值,然后线程B读取a后,然后执行打印b的值(根据原则二a一定为true),b的值一定为2。因为根据原则一,对b赋值Happens-Before对a赋值,再根据原则二,对a的赋值Happens-Before对a的读取,最后再根据原则三,对b的赋值Happens-Before对b的读取的,所以b一定为2。
四、管程中锁的原则
这个原则是指对同一个锁的解锁Happens-Before后续对这个锁的加锁。
int a = 1;
// 线程执行
synchronized (this){
if(a == 1){
a = 2;
}
}
上面代码中,线程A先对a进行赋值,然后解锁,线程B再加锁后,此时读到的a一定为2。
五、线程start原则
这条原则是关于线程启动的。它是指主线程A启动子线程B后,子线程B能够看到主线程在启动子线程B前的操作。也就是说如果线程A调用线程B的 start() 方法(即在线程A中启动线程B),那么该start()操作 Happens-Before 于线程B中的任意操作。
int a = 1;
Thread B = new Thread(() -> {
// 读取a
});
a = 2; // 假设能修改
B.start();
上面代码中,线程A先对a进行赋值,然后再启动线程B,所以线程B如果能够读取a的话(当然int类型,java中是不允许的),那么a一定为2。
六、线程join原则
这条是关于线程等待的。它是指主线程A等待子线程B完成(主线程A通过调用子线程B的join()方法实现),当子线程B完成后(主线程A中join()方法返回),主线程能够看到子线程的操作。
int a = 1;
Thread B = new Thread(() -> {
// 修改a
a = 2; // 假设能修改
});
B.start();
B.join();
// 读取a
上面代码中,读到的a一定为2。也就是说线程B中的操作对于B.join()后面的操作都是可见的。
相关文章
- JAVA 注解教程(四)Java 预置的注解
- java错误:The superclass "javax.servlet.http.HttpServlet" was not found on the Java Bu
- Java实现 LeetCode 409 最长回文串
- Java实现第八届蓝桥杯分巧克力
- java实现第七届蓝桥杯取球博弈
- Java实现 蓝桥杯 历届试题 小朋友排队
- Java实现 蓝桥杯VIP 算法提高 复数求和
- Java实现 蓝桥杯 算法提高 递推求值
- (转载)java多态(2)-------Java转型(向上或向下转型)
- 【JAVA】java中split以"." 、""、“|”分隔字符串
- bug_ _ java.lang.IllegalArgumentException: pointerIndex out of range 问题的两种解决办法
- 【JAVA】java中char类型数组用数组名打印结果不是地址值而是数组内容
- java中类加载时机
- java 实体序列化的意义
- 华为OD机试 - 迷宫问题(Java & JS & Python)
- 【java】Java经典面试题整理(附答案)
- 【java】Java 枚举(enum)如何使用以及原理
- 【java】Java ArrayList
- JAVA语言之Java 中不同的并行实现的性能比较
- Java基础(10)-JavaDoc命令行生成方式和Intellij IDEA 生成方式
- 【java】Java IO体系总览
- 【java】Java 内存模型
- java 设计模式详解