无法调用线程

Thread can't be called

class client
{
    static int data = 0;
    public static void main(String[] args)
    {
        new Thread(new Runnable() 
        {
            @Override
            public void run()
            {
                while(true)
                {
                    //System.out.print("");
                    if(data == 1) {System.out.println("GOTCHA");}
                }
            }
        }).start();
        Scanner sc = new Scanner(System.in);
        while(true)
        {
            data = sc.nextInt();
        }
    }
}

我不明白为什么当我输入 1 时它不起作用。 有一个有趣的情况,如果我删除评论(System.out.print(“”)),它会起作用。 我可以用另一种方式像回调方法一样,只是我想要的是为什么它不起作用。

简短的版本是,共享变量应该声明为 volatile 或者应该使用适当的同步机制来访问/更新变量。合适的同步机制可以是:

  • 原始监视器的使用;即 synchronized 具有相同目标对象的块或方法。

  • 在同一锁对象上使用 Lock.acquireLock.release

  • 其他 发生在 关系之前。 (不要担心这种情况。它很复杂。但如果你想,请阅读 Java 内存模型。)

无论如何,如果两个线程在没有适当同步的情况下共享一个(非易失性)变量,则不能保证一个线程1看到另一个线程写入的值.这就是您的示例所发生的情况。子线程永远看不到父线程的写入结果。

这是 Java 中多线程的正常行为。 Java 中的并发编程很棘手的原因之一。


1 - 在某些情况下数据会可见,而在其他情况下则不会。它可能取决于 Java 版本、操作系统、硬件平台、是否正在调试以及各种其他因素。可见性问题至少有两个可能的原因。 1)往往是由于内存缓存问题;例如一个线程所做的更改不会被刷新到主内存,以便另一个线程可以看到它们。 2) 或者,它可能(至少在理论上)是由于 JIT 编译器优化了内存提取。要准确了解发生了什么,您需要分析 JIT 编译器发出的本机代码。但无论哪种方式,这些行为都是 Java 内存模型 允许的 ... 如果所需的 关系不存在之前发生。