关于线程安全,我有一个很可能是愚蠢的问题。我有一个 ENUM 类,我的值定义如下:
public enum ThirdPartyContentSource {
DEV_TO("DevTo"),
MEDIUM("Medium"),
HASH_NODE("HashNode");
private String thirdPartyText;
ThirdPartyContentSource(String text) {
this.thirdPartyText = text;
}
public String getText() {
return this.thirdPartyText;
}
public static String valueOfCode(String thirdPartyCode) throws IllegalArgumentException {
ThirdPartyContentSource text = Arrays.stream(ThirdPartyContentSource.values())
.filter(val -> val.name().equals(thirdPartyCode))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unable to resolve ThirdPartyCode: " + thirdPartyCode));
return text.getText();
}
}
我的问题是,如果两个线程同时调用 valueOfCode() 方法,是否存在线程安全问题?
非常感谢
不会有任何线程安全问题,因为您没有修改其中的任何数据。不会有竞争条件或类似的东西。
将
thirdPartyText
标记为final
。那么你是线程安全的。
enum
对象本身(DEV_TO
、MEDIUM
、HASH_NODE
)都在其 enum
类加载时实例化。所以那里没有线程安全问题。
您的枚举类带有状态,
thirdPartyText
。该字段的内容是不可变的(String
)。这很好,因为不可变消除了一些并发问题。
我看到的唯一问题是对象引用是否在运行时发生变化,如果您要用另一个
String
对象替换一个 String
对象。显然,您希望此状态在运行时 not 发生变化。您可以通过将类成员字段声明为 final
来强制执行此操作。成为final
意味着不能将另一个对象分配给该引用变量。
private final String thirdPartyText; // Make this field `final`.
您的
valueOfCode
方法循环遍历枚举(通过 .values
调用),这在运行时不会改变。所以那里没有线程安全问题。
你的
valueOfCode
方法访问我们通过制作thirdPartyText
修复的final
字段,所以这些值在运行时不会改变。所以那里没有线程安全问题。
您对
valueOfCode
的意图不明确——请参阅问题上发表的评论。但我在那里没有看到线程安全问题。
虽然我不是并发专家,但在进行
final
更改后,您的代码对我来说看起来是线程安全的。