gpt4 book ai didi

java - 使用 AtomicBoolean 控制实例的状态

转载 作者:行者123 更新时间:2023-12-01 16:53:24 27 4
gpt4 key购买 nike

我需要确保每个实例生命周期仅执行一次特定的启动和停止代码,并且该实例无法“重新启动”。以下代码足以满足多个线程可能对实例进行操作的场景吗?

public final class MyRunnable {
private final AtomicBoolean active = new AtomicBoolean(false);
private final AtomicBoolean closed = new AtomicBoolean(false);

public void start() {
if (closed.get()) {
throw new IllegalStateException("Already closed!");
}
if (active.get()) {
throw new IllegalStateException("Already running!");
}

active.set(true);

// My one-time start code.

// My runnable code.
}

public void stop() {
if (closed.get()) {
throw new IllegalStateException("Already stopped!");
}
if (!active.get()) {
throw new IllegalStateException("Stopping or already stopped!");
}

active.set(false);

// My one-time stop code.

closed.set(true);
}
}

最佳答案

出于两个原因,我会选择单一的三值状态。

首先,在 active,close “元组”的 4 个可能值中,只有 3 个有意义,将两者都设置为 true 会导致(可能是良性的,但尽管如此)无效状态。您可能会认为它纯粹是迂腐,但清晰的设计通常会带来其他好处。

这巧妙地将我们引向了第二个更可怕的原因:

 active.set(false);
// <-- what if someone calls start() here?
closed.set(true); //I assume you wanted to set it to true

正如您从我的评论中看到的,您那里有一个漏洞,在您将 active 设置为 后,有人可能会调用 start() >false 但在将 close 设置为 true 之前。

现在你可能会说“好吧,让我们交换这两个然后先设置关闭”,但是你必须解释为什么这两个肯定不会被JVM重新排序。最终,您可能会将两个标志都设置为 true,从而导致上述“无效状态”。

这里还有另一个单独的问题:您遵循的模式是调用 get() 来检查值,然后set() 将其设置为其他值。如PetrosP pointed it out ,这不是一个原子操作,您可以调用 start() 1000 次,所有这些都将 active 视为 false。您需要使用 compareAndSet 来代替,它 是原子的(这是 Atomic* 类的全部要点),从而保证只有一个线程可以推进状态标志。

因此,让我们使用单个 3 值状态将两者结合起来(为了简单起见,我使用了 AtomicInteger,但您可以使用 AtomicReference 和真正的 枚举)和compareAndSet():

public final class MyRunnable {
private static final int READY_TO_START = 0;
private static final int ACTIVE = 1;
private static final int STOPPED = 2;
private final AtomicInteger status = new AtomicInteger(READY_TO_START);

public void start() {
if (!status.compareAndSet(READY_TO_START, ACTIVE)) {
throw new IllegalStateException("Already started");
}

// My one-time start code.
}

public void stop() {
if (!status.compareAndSet(ACTIVE, STOPPED)) {
throw new IllegalStateException("Can't stop, either not started or already stopped");
}

// My one-time stop code.
}
}

关于java - 使用 AtomicBoolean 控制实例的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36085736/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com