今天我看到了一个关于AtomicEnum的实用类,但我想知道为什么Java标准库中没有包含原子枚举。事实上,我非常怀疑它是否真正是原子性的,以及这个实用类是否有效。
AtomicEnum类是这里。
- 我该如何检查它是否可以原子操作?
- 是否有工具可以查看编译后的代码,并确信它只执行了一条机器指令?
- 是否可能从代码中发现它是否原子化?
- 因此,如果这个原子枚举有效,我可以拥有一个属性AtomicEnum,并且可以在不使用volatile关键字和同步getter和setter的情况下安全地使用它吗?
今天我看到了一个关于AtomicEnum的实用类,但我想知道为什么Java标准库中没有包含原子枚举。事实上,我非常怀疑它是否真正是原子性的,以及这个实用类是否有效。
AtomicEnum类是这里。
今天我看到了这个
AtomicEnum
的实用类,但我不知道为什么它不包含在Java标准库中,如果有一个原子性的枚举,它是否可能存在?
你提供的 AtomicEnum
类只是对 AtomicReference
类做了一层封装,它可以给任何 Object
提供并发访问。
如果你需要多个线程同时获取和设置枚举值,那么一个 volatile enumField
就足够了。使用 volatile
关键字可以确保一个线程所做的更新操作能被其他线程看到。
如果你需要执行类似 compareAndSet(...)
的原子操作 - 即测试字段是否具有特定值,如果是则进行更新,那么你需要使用 AtomicReference
。你可以使用如下代码来实现:
private final AtomicReference<MyEnum> atomicColor = new AtomicReference<>();
...
atomicColor.set(ColorEnum.RED);
...
if (atomicColor.compareAndSet(ColorEnum.RED, ColorEnum.GREEN)) {
...
}
...
ColorEnum color = atomicColor.get();
我该如何检查它是否原子地执行操作?
AtomicReference
是 java.util.concurrent
类库的一部分,已经经过了充分的测试。
有没有工具可以查看编译后的代码,确保它只是一条机器指令?
这并不是必要的。如果您想知道它在做什么,可以查看 AtomicReference
的源代码。不幸的是,真正的魔力在于 sun.misc.Unsafe
的本地代码中。
能否从代码中发现它?
这并不是必要的。
如果此原子枚举(Atomic enum)起作用,那么我可以有一个 AtomicEnum 属性,并且可以在没有 volatile 关键字和同步 getter 和 setter 的情况下安全使用它吗?
是的,AtomicReference
包装了一个 volatile V value
,因此您不必这样做。
AtomicReference
使您的字段原子化,因此多个线程可以原子地测试和更改它以不同的枚举。@Johnny - Grayvolatile
的原因是为了进行内存同步。如果一个线程更改了共享的enum,其他线程不一定能看到更新。我们使用AtomicReference
的原因是可以原子性地执行 compareAndSet(...)
操作。如果您不需要原子方法(即只设置或获取它),那么一个volatile enumField
就足够了。但是如果有多个线程,您需要使用volatile
。@Johnny。 - GrayAtomicEnum
只是一个轻量级的包装器,封装了一个AtomicReference
。这是有道理的,因为enum
值本质上就是一个对象(引用)。
所以,如果AtomicReference
正常工作(我认为我们可以假设它会),AtomicEnum
也将正常工作。
enum Weekdays {
public int rank = 0;
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY;
}
AtomicEnum<Weekdays> today = Weekdays.TUESDAY;
today.rank = 3;
不能保证每个线程都有更新后的排名。(排名不是易失性的。每个人在缓存中维护着对象的单独副本。)
因此,引用访问是原子的,但对象访问不是。
注意:
1)原子访问并不意味着在一条机器指令中执行。但从逻辑上可以这样想。虽然它是不可分割的,但它可以包含多条指令。
2)即使存在这样的工具,测试它也会非常困难,因为更新过程几乎是不可预测的。因此,可能会出现误报结果。
希望这可以帮助你。
AtomicReference<SomeEnum>
版本,那么这就很令人困惑了。在第一种情况下,你是正确的,但在第二种情况下,你可以确保获得必要的可见性保证。对我来说,它读起来好像你在第二种情况下也在谈论AtomicReference(或者更准确地说是AtomicEnum),你可能只需要重新表达一下。 - Voo我认为写这样的类没有任何意义。事实上,如果您正在编写此类,您需要重新考虑类的责任。 ENUM绝对是线程安全的,所以我不确定为什么有人需要AtominEnum,或者它只是某个类是原子性的并且还使用了一些枚举,但是将其命名为AtomicEnum非常令人困惑,不利于设计或命名约定。