当前位置: 首页 > 面试题库 >

如何演示Java多线程可见性问题?

欧阳德运
2023-03-14
问题内容

如果从多个线程访问Java中的变量,则必须确保安全发布它们。这通常意味着使用synchronizedvolatile

我的印象是,我的一些同事没有认真对待这个问题,因为他们“从未听说volatile过,他们的程序已经工作了很多年”。

所以我的问题是:

有人可以提供一个示例Java程序/片段来可靠地显示数据可见性问题。

我认为运行程序并看到意外的NPE或过时的变量值会比理论上的解释更有帮助,这是无法证明的。

非常感谢你的帮助!

更新: 只是再次强调这一点。我已经阅读了 Java Concurreny in Practice, 并了解了 理论上
存在可见性问题的示例。我正在寻找的是一种实际 演示 它们的方法。我不确定这是否确实可行,但是也许有jvm配置或类似的配置允许它。


问题答案:

通过删除操作修改此处的示例,我得出一个示例

提出强调使用volatile重要性的最常见示例是while(keepRunning):

public class Test extends Thread {

    boolean keepRunning = true;

    public static void main(String[] args) throws InterruptedException {
        Test t = new Test();
        t.start();
        Thread.sleep(1000);
        t.keepRunning = false;
        System.out.println(System.currentTimeMillis() + ": keepRunning is false");
    }

    public void run() {
        while (keepRunning) 
            System.out.println(System.currentTimeMillis() + ": " + keepRunning);
    }
}

由于keepRunning可以(有效地)保留在运行while循环的线程的高速缓存中,因此在将程序设置为false keepRunning后,该程序可能会长时间打印“ true” keepRunning

但是请注意,没有公开竞争条件的可靠方法。(请参阅我的其他答案。)在某些情况下,此示例可能在硬件/操作系统/ jvm的某些组合中公开。

该示例在我的环境中始终失败(线程永不停止运行)。

// Java environment:
// java version "1.6.0_0"
// OpenJDK Runtime Environment (IcedTea6 1.6.1) (6b16-1.6.1-3ubuntu3)
// OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode)
public class Test2 extends Thread {
    boolean keepRunning = true;
    public static void main(String[] args) throws InterruptedException {
        Test2 t = new Test2();
        t.start();
        Thread.sleep(1000);
        t.keepRunning = false;
        System.out.println(System.currentTimeMillis() + ": keepRunning is false");
    }
    public void run() {
        while (keepRunning) 
        {}
    }
}

注意,这类问题完全取决于编译器/运行时/系统。特别是,编译器可以确定添加指令以从内存中读取变量,即使它不是易失性的(这样代码也可以工作),因此vm和jit可以优化从内存中的读取操作,仅使用寄存器,甚至可以使用寄存器。处理器可以对指令重新排序-
不会影响这种情况,但是在其他多线程情况下,如果修改了多个变量,它可能会影响其他线程的感知状态。



 类似资料:
  • 我正在学习Java的易失性,我的代码是这样的。 我知道如果flag没有volatile,线程就不会存在。这是能见度的问题。 但是,如果我在while循环中编写一些代码,如,t1线程将读取新值并停止循环。 我知道如何使用volatile来解决可见性问题,所以我的问题是: 为什么当我写?

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

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

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

  • Workerman有一个依赖pthreads扩展的MT多线程版本,但是由于pthreads扩展还不够稳定,所以这个Workerman多线程版本已经不再维护。 目前Workerman及其周边产品都是基于多进程单线程的。

  • 全球销量第一的表格控件,类似Excel的强大功能 Spread for ASP.NET表格控件兼容Excel的强大功能,并将其嵌入到您的应用系统中。完备的Excel文档支持使得您可以在企业中分享和访问数据信息;内嵌的图表引擎和数据可视化支持让您更加轻松的为商务、工程以及科学应用系统中创建丰富高效的信息中心。