创建可取消线程是否需要AtomicBoolean? [英] Is AtomicBoolean needed 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);
}
}
但是我不确定cancelPending是否一定是AtomicBoolean.在这种情况下,我们可以只使用普通的布尔值吗?
不需要同时使用volatile
和AtomicBoolean
.如果将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屋!