Java 螺纹可以';别叫了

Java 螺纹可以';别叫了,java,multithreading,infinite-loop,Java,Multithreading,Infinite Loop,我不明白为什么我输入1时它不起作用。 还有一个有趣的情况是,如果我删除注释(System.out.print(“”)),它就会工作。 我可以用另一种方法,比如回调方法,我只想知道它为什么不起作用。简短的版本是,共享变量应该声明为volatile,或者应该使用适当的同步机制访问/更新变量。适当的同步机制可以是: 使用原始监视器;i、 e.与同一目标对象同步的块或方法 使用锁。在同一个锁对象上获取和锁。释放 在建立关系之前,还发生了其他一些适当的事情。(不要担心这个问题。它很复杂。但如果您想了解J

我不明白为什么我输入1时它不起作用。 还有一个有趣的情况是,如果我删除注释(System.out.print(“”)),它就会工作。
我可以用另一种方法,比如回调方法,我只想知道它为什么不起作用。

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

  • 使用原始监视器;i、 e.
    与同一目标对象同步的
    块或方法

  • 使用
    锁。在同一个锁对象上获取
    锁。释放

  • 在建立关系之前,还发生了其他一些适当的事情。(不要担心这个问题。它很复杂。但如果您想了解Java内存模型,请仔细阅读。)

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

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



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

这样的紧密循环在线程上非常粗糙。您可以尝试
volatile static int data
。谢谢!它起作用了!但我仍然对评论有疑问。在我的假设中,当System.out.print()启动时,CPU缓存同步主存?除非有同步或易失性,否则无法保证新线程何时会看到变量的更新值。至于为什么System.out.println会有所不同,它将是特定于平台的、特定于jvm的,甚至可能是特定于运行的。就像你可能试过几次,但如果你试过几百次,你会看到不同的行为。换句话说,我不知道。:)也是这样一个紧密的循环,而(True){System.out.print(“”;}可能会弄乱您的std输入/输出缓冲区。
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();
        }
    }
}