使用 clone() 和非 final 字段的流利类的线程安全 [英] Thread safety of a fluent like class using clone() and non final fields
问题描述
这个 fluent like 类并不是严格不可变的,因为字段不是最终的,但它是线程安全的,为什么?
This fluent like class is not strictly immutable because the fields are not final, but is it thread safe, and why?
我关心的线程安全问题不是竞争条件,而是变量的可见性.我知道有一种使用最终变量和构造函数而不是 clone() + 赋值的解决方法.我只是想知道这个例子是否是一个可行的替代方案.
The thread safety issue I'm concerned with is not the race condition, but the visibility of the variables. I know there is a workaround using final variables and a constructor instead of clone() + assignment. I just want to know if this example is a viable alternative.
public class IsItSafe implements Cloneable {
private int foo;
private int bar;
public IsItSafe foo(int foo) {
IsItSafe clone = clone();
clone.foo = foo;
return clone;
}
public IsItSafe bar(int bar) {
IsItSafe clone = clone();
clone.bar = bar;
return clone;
}
public int getFoo() {
return foo;
}
public int getBar() {
return bar;
}
protected IsItSafe clone() {
try {
return (IsItSafe) super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(e);
}
}
}
推荐答案
您在设置字段时没有持有锁,并且正如您自己提到的,该字段不是最终的.
You are not holding a Lock while setting the field and as you mention yourself the field is not final.
因此,从可见性的角度来看,这种方法不是线程安全的.
Therefore from a visibility standpoint this approach is not thread-safe.
这里有一些进一步的说明:https://stackoverflow.com/a/9633968/136247
Some further clarifications here: https://stackoverflow.com/a/9633968/136247
关于使用 volatile 的问题的更新:
为了论证使用 volatile 修复了这里的线程问题.
但是,您应该重新考虑 final 字段和复制构造函数,因为:
For the sake of the argument using volatile fixes the threading issue here.
However you should reconsider final fields and a copy constructor because:
- 字段访问会稍微快一点(读取总是来自 cpu 缓存)
- 避免不鼓励使用
clone
(请参阅 Josh Bloch 的 Effective Java) - 具有 final 字段的构造函数是不可变类的已知习语,代码的读者很容易识别
- 标记字段
volatile
而打算使它们不可变本身就是一个矛盾;)
- Field access will be slightly faster (the reads can always come from the cpu cache)
- You avoid the discouraged use of
clone
(see Effective Java by Josh Bloch) - Constructor with final fields is a known idiom for immutable classes and will be easily recognised by readers of the code
- Marking fields
volatile
while intending for them to be immutable is a contradiction in and of itself ;)
这篇关于使用 clone() 和非 final 字段的流利类的线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!