代码之家  ›  专栏  ›  技术社区  ›  Scorb

从其他线程访问while循环bool是否安全?

  •  1
  • Scorb  · 技术社区  · 6 年前

    我正在编写一些Java代码,并有一个伪造的例子,我不确定这是否是线程安全的代码。

    基本上我有一个while循环来检查bool,我想从另一个线程设置bool为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 回复  |  直到 6 年前
        1
  •  3
  •   Oleksandr Pyrohov Andreas    6 年前

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

    private static volatile boolean mRunning = false;
    

    如果只有一个唯一的线程修改变量,而其他线程只读取该变量,则不需要额外的同步, 不稳定的 就足够了(它保证任何读取字段的线程都能看到最近写入的值)。

    我应该这样做吗?

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

    你可以,但你不应该!无论如何,你会有意想不到的行为(这个 answer 解释原因)。

    在问题中描述的情况下,只需使用 不稳定的 变量,也不那么冗长,其性能可能会更好地与 synchronized 封锁。

        2
  •  2
  •   davidxxx    6 年前

    此代码是否会导致不良行为?

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

    所以 开始() 可以继续循环 while 陈述。

    因此,必须确保共享标志被声明为 volatile boolean mRunning 是的。