Happens-Before原则是Java内存模型(JMM)中定义的一种偏序关系,用于确定两个操作之间的相对顺序。
如果操作A happens-before 操作B,那么操作A的结果对操作B是可见的,且操作A的执行顺序在操作B之前。这就意味着,当线程B读取到线程A写入的值时,可以确保线程A的写入操作已经发生。
在一个线程内,按照程序顺序执行的操作自然满足Happens-Before原则。这是因为单个线程内的操作是顺序执行的,没有并发访问的问题。
举个栗子:
int a = 1; // 操作A
int b = a; // 操作B
在这个例子中,操作A(给变量a赋值为1)happens-before操作B(读取变量a的值并赋给变量b)。所以,操作B读取到的b的值一定是1。
当一个线程释放锁时,它之前对共享变量的修改对其他线程是可见的;当一个线程获取锁时,它可以读取到之前释放锁线程对共享变量的修改。这里,锁的释放操作happens-before锁的获取操作。
举个栗子:
Object lock = new Object();
int sharedVariable = 0;
// 线程A
synchronized(lock) {
sharedVariable = 1; // 操作A
} // 释放锁
// 线程B
synchronized(lock) {
int temp = sharedVariable; // 操作B
} // 获取锁
对于上面的栗子,线程A在释放锁之前将sharedVariable
赋值为1(操作A)。由于锁的释放操作happens-before锁的获取操作,线程B在获取锁后读取到的sharedVariable
的值一定是1。
对volatile变量的写操作happens-before后续对该变量的读操作。这就意味着,当一个线程写入一个volatile变量时,其他线程可以立即看到这个修改。
举个栗子:
volatile boolean flag = false;
// 线程A
flag = true; // 操作A
// 线程B
if (flag) { // 操作B
// ...
}
上面的代码中,线程A将volatile变量flag
设置为true
(操作A)。因为volatile变量的写操作happens-before读操作,线程B在读取flag
时,一定能够看到其值为true
。
线程的启动(start)操作happens-before此线程内的任意操作。线程的所有操作都happens-before其他线程检测到该线程已经终止(通过Thread.join()方法或Thread.isAlive()的返回值等方法)。
举个例子:
Thread thread = new Thread(() -> {
// 线程内操作
System.out.println("xiaowei haoshuai!");
});
thread.start(); // 操作A
thread.join(); // 操作B
上面的代码中,线程启动操作(操作A)happens-before线程内的打印操作,而线程内的打印操作又happens-before线程终止检测操作(操作B)。因此,主线程在调用thread.join()
方法时,可以确保子线程已经执行了打印操作。
Happens-Before原则是并发编程中的基石,它定义了线程间操作顺序和可见性的保证。
我们理解并遵循这一原则,就可以编写出正确且可预测的并发程序。本篇文章到此结束,希望我们开发者们在编写代码时都牢记住这一原则哦!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。