国外的有名的网站阿里云虚拟主机多个网站
news/
2025/9/30 5:30:16/
文章来源:
国外的有名的网站,阿里云虚拟主机多个网站,上高县建设局网站,微信小程序开发2、happens-before 关系
在 Java 中#xff0c;volatile 关键字用于变量的修饰#xff0c;它确保对该变量的所有读写操作都是直接从主内存中进行的#xff0c;而不是从线程的本地缓存
中读取。volatile 关键字可以保证某些类型的内存可见性#xff0c;并在一定程度上防止…2、happens-before 关系
在 Java 中volatile 关键字用于变量的修饰它确保对该变量的所有读写操作都是直接从主内存中进行的而不是从线程的本地缓存
中读取。volatile 关键字可以保证某些类型的内存可见性并在一定程度上防止指令重排序。具体来说volatile 可以建立一种特殊
的 happens-before 关系确保多线程程序的正确性和一致性。
happens-before 关系是 Java 内存模型JMM中的一种重要概念用于定义线程之间操作的顺序性。简单来说如果操作 A happens-
before 操作 B那么操作 A 的结果对操作 B 是可见的并且操作 A 的顺序在操作 B 之前。
对于 volatile 变量有以下几种 happens-before 关系
对 volatile 变量的写操作 happens-before 随后的读操作 如果线程 A 对一个 volatile 变量进行写操作然后线程 B 对这个 volatile 变量进行读操作那么在 A 线程中对这volatile 变量的写操作 happens-before B 线程中的读操作。这意味着线程 B 将看到线程 A 写入的最新值。 对 volatile 变量的写操作会禁止写之前的所有操作被重排序到写操作之后 在对 volatile 变量进行写操作之前的所有操作在内存模型上会被“刷回”主内存。即对 volatile 变量的写操作之前的所有普通变量的操作都将在写操作之前完成并且在写操作之前的所有操作对后续的任何线程都是可见的。 对 volatile 变量的读操作会禁止读之后的所有操作被重排序到读操作之前 在对 volatile 变量进行读操作之后的所有操作在内存模型上会从主内存读取最新值。即对 volatile 变量的读操作之后的所有普通变量的操作都将在读操作之后完成并且在读操作之后的所有操作将看到写操作之后的最新结果。
示例代码
以下是一个简单的代码示例展示了 volatile 的 happens-before 关系
public class VolatileHappensBeforeExample {
// private volatile boolean flag false;private boolean flag false;private int counter 0;public void writer() {counter 1; // 普通写操作flag true; // volatile 写操作}public void reader() {if (flag) { // volatile 读操作System.out.println(counter); // 普通读操作}}public static void main(String[] args) {VolatileHappensBeforeExample example new VolatileHappensBeforeExample();for (int i 0; i 10; i) {// 创建写线程Thread writerThread new Thread(() - {example.writer();});// 创建读线程Thread readerThread new Thread(() - {example.reader();});writerThread.start();readerThread.start();}}
}在这个示例中
writer() 方法中对 flag 的写操作 happens-before 随后的 reader() 方法中对 flag 的读操作。因此如果 reader() 方法检测到 flag 为 true则它必然会看到 counter 的值为 1即 writer() 方法中的写操作已发生。
这种 happens-before 关系确保了多线程环境中的变量更新对于其他线程是可见的从而保证了线程之间的正确通信。
上面这么啰里巴嗦地讲这也太抽象了即使去掉 volatile 修饰其实也不一定会出现打印不出来1的情况必须整个程序验证一下。
验证 happens-before 关系
验证不使用 volatile 关键字会导致错误可以通过编写一个多线程测试程序观察在不同线程之间的共享变量是否会出现不可见性问题。具体来说可以通过运行代码并检测在某些情况下是否会出现预期之外的结果例如永远不会打印出预期的值
要验证不使用 volatile 关键字会导致错误可以通过编写一个多线程测试程序观察在不同线程之间的共享变量是否会出现不可见性问题。具体来说可以通过运行代码并检测在某些情况下是否会出现预期之外的结果例如永远不会打印出预期的值。
验证代码
以下是一个示例代码通过多个线程的交互来验证如果不使用 volatile 关键字会出现的问题
public class VolatileHappensBeforeExample {
// private boolean flag false; // 没有使用 volatileprivate volatile boolean flag false; // 使用 volatileprivate int counter 0;public void writer() {counter 1; // 普通写操作flag true; // 普通写操作System.out.println(Thread.currentThread().getName() set flag to true);}public void reader() {while (!flag) {// Busy-wait loop, waiting for flag to become true}System.out.println(Thread.currentThread().getName() sees flag is true and counter is counter);}public static void main(String[] args) {VolatileHappensBeforeExample example new VolatileHappensBeforeExample();// 创建写线程Thread writerThread new Thread(() - {try {Thread.sleep(100); // 确保 reader 线程先启动} catch (InterruptedException e) {Thread.currentThread().interrupt();}example.writer();}, WriterThread);// 创建读线程Thread readerThread new Thread(() - {example.reader();}, ReaderThread);readerThread.start();writerThread.start();try {readerThread.join();writerThread.join();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}代码解释
writer() 方法 设置 counter 为 1。设置 flag 为 true。打印当前线程名称及其操作。 reader() 方法 使用一个 busy-wait 循环等待 flag 变为 true。当 flag 为 true 时打印当前线程名称及其看到的 counter 值。 main 方法 创建并启动 writerThread 和 readerThread。使用 Thread.sleep(100) 确保 readerThread 先启动。
可能的结果
运行上述代码多次可能会看到以下结果
有时程序会如预期输出 WriterThread set flag to true 和 ReaderThread sees flag is true and counter is 1。但在某些运行中可能会看到 WriterThread set flag to true但 readerThread 进入 busy-wait 循环后永远不会退出。这是因为 readerThread 可能无法看到 flag 被设置为 true 的更新。
结论
如果不使用 volatile 关键字flag 的写入更新对其他线程不可见导致 readerThread 无法检测到 flag 的变化并一直在 busy-wait 循环中。这验证了不使用 volatile 关键字时可能出现的内存可见性问题。
通过多次运行这个程序观察到 readerThread 不会始终成功读取到 flag 的变化就可以确认不使用 volatile 关键字会导致多线程程序中的错误。这种错误在 volatile 关键字存在时不会发生因为 volatile 能确保内存可见性和建立正确的 happens-before 关系。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/922491.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!