首页 > 解决方案 > 无法调用线程

问题描述

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(“”)),它会起作用。我可以用另一种方式,比如回调方法,只是我想要的是为什么它不起作用。

标签: javamultithreadinginfinite-loop

解决方案


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

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

  • 在同一个锁对象上使用Lock.acquire和。Lock.release

  • Something else with appropriate happens before relationships. (Don't worry about this case. It is complicated. But if you want to, read up about the Java Memory Model.)

At any rate, if two threads share a (non-volatile) variable without appropriate synchronization, then one thread is not guaranteed1 to see the value written by the other thread. That is what was happening with your example. The child thread never sees the results of the parent thread's write.

This is normal behavior with multi-threading in Java. And one of the reasons why concurrent programming in Java is tricky.


1 - In some cases the data will be visible, and others it won't. It can depend on the Java version, the operating system, the hardware platform, whether you are debugging or not, and various other things. There are at least two possible causes of the visibility issues. 1) It is often due to memory caching issues; e.g. changes made by one thread not being flushed to main memory so that the other thread can see them. 2) Alternatively, it could (in theory at least) be due the JIT compiler optimizing away memory fetches. To understand exactly what is going on, you would need to analyze the native code emitted by the JIT compiler. But either way, these behaviors are permitted by the Java Memory Model ... if the required happens before relationships do not exist.


推荐阅读