无法调用线程

问题描述 投票:0回答:1
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时它不起作用。并且有一种有趣的情况,如果我删除comment(System.out.print(“”)),它会起作用。我可以像回调方法那样用另一种方式,只是我想要的是为什么它不起作用。

java multithreading infinite-loop
1个回答
1
投票

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

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

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

  • 具有适当的在……之前]关系的其他东西。 (不必担心这种情况。它很复杂。但是,如果您愿意,请阅读Java内存模型。)

  • 无论如何,如果两个线程共享一个(非易失性)变量而没有适当的同步,则不能保证一个线程1

来查看另一线程写入的值。这就是您的示例所发生的情况。子线程永远不会看到父线程的写入结果。

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


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

...如果不存在所需的happens before关系。

0
投票

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

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

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

  • 具有适当的在……之前]关系的其他东西。 (不必担心这种情况。它很复杂。但是,如果您愿意,请阅读Java内存模型。)

  • 无论如何,如果两个线程共享一个(非易失性)变量而没有适当的同步,则不能保证一个线程1

来查看另一线程写入的值。这就是您的示例所发生的情况。子线程永远不会看到父线程的写入结果。

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


1-在某些情况下,数据将可见,在其他情况下则将不会。它可能取决于Java版本,操作系统,硬件平台,是否在调试以及其他各种情况。

© www.soinside.com 2019 - 2024. All rights reserved.