创建可取消线程是否需要AtomicBoolean? [英] Is AtomicBoolean needed to create a cancellable thread?

查看:115
本文介绍了创建可取消线程是否需要AtomicBoolean?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常使用以下模式创建可取消线程:

public class CounterLoop implements Runnable {

    private volatile AtomicBoolean cancelPending = new AtomicBoolean(false);

    @Override
    public void run() {
        while (!cancelPending.get()) {
            //count
        }
    }

    public void cancel() {
        cancelPending.set(true);
    }
}

但是我不确定cancelPending是否一定是AtomicBoolean.在这种情况下,我们可以只使用普通的布尔值吗?

解决方案

不需要同时使用volatileAtomicBoolean.如果将cancelPending变量声明为final,如下所示:

private final AtomicBoolean cancelPending = new AtomicBoolean(false);

final字段的JLS语义意味着不需要同步(或volatile).所有线程将为cancelPending引用看到正确的值. JLS 17.5 状态:

对象的构造函数完成后,即认为该对象已完全初始化.只有在该对象完全初始化之后才可以看到对该对象的引用的线程保证可以看到该对象的final正确初始化的值字段."

...但是普通字段没有这样的保证;即不是final也不是volatile.

您也可以只将cancelPending声明为volatile boolean ...,因为您似乎没有使用AtomicBoolean的测试和设置功能.<​​/p>

但是,如果您使用非易失性boolean,则需要使用synchronized来确保所有线程都能看到cancelPending标志的最新副本.

I often use the following pattern to create a cancellable thread:

public class CounterLoop implements Runnable {

    private volatile AtomicBoolean cancelPending = new AtomicBoolean(false);

    @Override
    public void run() {
        while (!cancelPending.get()) {
            //count
        }
    }

    public void cancel() {
        cancelPending.set(true);
    }
}

But I'm not sure that cancelPending MUST be a AtomicBoolean. Can we just use a normal boolean in this case?

解决方案

Using both volatile and AtomicBoolean is unnecessary. If you declare the cancelPending variable as final as follows:

private final AtomicBoolean cancelPending = new AtomicBoolean(false);

the JLS semantics for final fields mean that synchronization (or volatile) will not be needed. All threads will see the correct value for the cancelPending reference. JLS 17.5 states:

"An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields."

... but there are no such guarantees for normal fields; i.e. not final and not volatile.

You could also just declare cancelPending as a volatile boolean ... since you don't appear to be using the test-and-set capability of AtomicBoolean.

However, if you used a non-volatile boolean you would need to use synchronized to ensure that all threads see an up-to-date copy of the cancelPending flag.

这篇关于创建可取消线程是否需要AtomicBoolean?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆