从其他线程访问while循环布尔值是否安全?

时间:2018-06-23 20:07:31

标签: java multithreading thread-safety

我正在编写一些Java代码,并有一个人为的示例,并且我不确定这是否是线程安全代码。

基本上,我有一个while循环来检查布尔值,我想从另一个线程将该布尔值设置为false。

遵守以下内容

    public void start() {
    mRunning = true;

    thread = new Thread()
    {
        public void run()
        {
            while (mRunning) {

            }
        }
    }
    thread.start();
}

然后我在该类上有一个可变器,可以从另一个线程调用它。

public void stop() {
    mRunning = false;
}

此代码会导致不良行为吗?如果是这样,我应该只是这样做吗?

public void stop() {
    sychronized(this) {
        mRunning = false;
    }
}

2 个答案:

答案 0 :(得分:3)

如果仅需要线程间通信,而不需要mutual exclusion,请使用volatile变量:

private static volatile boolean mRunning = false;

如果只有一个唯一的线程修改一个变量,而其他线程仅读取该变量,则您不需要额外的同步,volatile就足够了(它保证读取该字段的任何线程都将看到最新的线程。书面价值)。

  

我应该这样做吗?

public void stop() {
    synchronized (this) {
        mRunning = false;
    }
}

可以,但是不可以!无论如何,您都会得到意想不到的行为(此answer解释了原因)。

在问题描述的情况下,只需使用volatile变量,该变量也不那么冗长,并且与synchronized块相比,其性能可能更好。

答案 1 :(得分:2)

  

此代码会导致不良行为吗?

可以。
stop()中的线程将能够将共享false字段的值设置为boolean mRunning
但是,如果未将此字段声明为start(),则volatile中的线程可能看不到更改,因为执行start()的线程不会使用当前对象的监视器,因此线程内存状态可能与主内存状态不同。

因此start()可以继续在while语句中循环。

因此,您必须确保将共享标志声明为volatile boolean mRunning