当前位置: 首页 > 知识库问答 >
问题:

Java多线程变量可见性问题[重复]

督瑞
2023-03-14

我正在学习Java的易失性,我的代码是这样的。

public class Test {
    public static boolean flag = true;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            while(flag){
                // System.out.println(flag);
            }
            System.out.println("end");
        });
        t1.start();

        Thread.sleep(100);

        Thread t2 = new Thread(()->{
            flag = false;
            System.out.println("changed");
        });
        t2.start();
    }
}

我知道如果flag没有volatile,线程就不会存在。这是能见度的问题。

但是,如果我在while循环中编写一些代码,如System.out.println("abc"),t1线程将读取新值并停止循环。

我知道如何使用volatile来解决可见性问题,所以我的问题是:

为什么当我写System.out时,t1可以读取标志的新值。while循环中的println(“abc”)

共有1个答案

叶声
2023-03-14

当您这样做时:

while(flag){
     // System.out.println(flag);
}

您将具有空体的循环,这可能导致在场上旋转所知道的;从源头可以读到:

在空循环语句的条件下重复读取非易失性字段可能会导致无限循环,因为编译器优化可能会将此字段访问移出循环。

但是,通过添加语句< code > system . out . println(flag);在你的循环中,你要避开旋转磁场。尽管如此,如果线程< code>t1从其高速缓存中读取值为< code>true的字段< code>flag,则该线程将仅在存储该字段值的高速缓存行无效时停止,并且该线程从主存储器中获得新的更新值< code>flag字段(即< code>flag=false)。

除其他事项外,易失性可确保线程将读取标志字段的最大更新值。因此,使字段标志可变可确保:

  while(flag){
    // System.out.println(flag);
}

潜在的编译器优化不会将对字段标志的访问移出循环

但是,如果我在 while 循环中编写一些代码,如 System.out.println(“abc”),则线程 t1 将读取新值并停止循环。

这是双重的:首先,通过添加< code > System.out.println(" ABC ")您将避免自旋场问题;其次,如果查看system . out . println代码:

   public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }

您可以看到有一个synchronized被调用,这将增加线程不是从缓存而是从主内存读取字段标志的可能性。

 类似资料:
  • 问题内容: 如果从多个线程访问Java中的变量,则必须确保安全发布它们。这通常意味着使用或。 我的印象是,我的一些同事没有认真对待这个问题,因为他们“从未听说过,他们的程序已经工作了很多年”。 所以我的问题是: 有人可以提供一个示例Java程序/片段来可靠地显示数据可见性问题。 我认为运行程序并看到意外的NPE或过时的变量值会比理论上的解释更有帮助,这是无法证明的。 非常感谢你的帮助! 更新: 只

  • 问题内容: 当我阅读“ 实践中的Java并发性 ” c03时,我对以下程序感到困惑: 由于重新排序和线程可见性,循环可能永远不会停止,或者输出可能为零,但是我已经尝试了很多次,并且输出始终为42。所有原因是我太幸运了吗? 问题答案: 所有的原因是我太幸运了吗? 不必要。这也将取决于您的处理器体系结构和JVM实现。那就是微妙的内存模型问题的问题之一:它们很难在野外复制。

  • 如何从多个线程同时访问静态变量。 如果我有这样的课 我需要访问线程1的值,比如 从线程2中,我需要设置如下值 这会导致内存冲突吗?。如果是,建议使用什么方法来处理这种情况?。

  • 1):单线程应用程序只会在用户的CPU上使用1个线程吗?提供更多的线程会使用多个CPU内核吗?如果声明的线程比用户的CPU多,会发生什么?

  • 本文向大家介绍浅析Python多线程下的变量问题,包括了浅析Python多线程下的变量问题的使用技巧和注意事项,需要的朋友参考一下 在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁。 但是局部变量也有问题,就是在函数调用的时候,传递起来很麻烦: 每个函数一层一层调用都这么传参数那还得了?用

  • 如图所示, 位置 2 和位置3 为什么可以访问 位置1 (也就是主线程)的 point 局部变量 ? 毕竟 位置 2 和位置3 是另外两个线程啊 !! 当我加上 第10行代码后,thread1 和 thead2 中都不能访问主线程中的point 了。我知道这是内部类的“事实最终变量” 的限制。 如下图所示,就是我不理解的地方。(在 “栈内存” 层面) 我的猜测:之所以 thread1 和 trea