如果我有课程Foo
public class Foo implements Serializable, Cloneable {
public Foo() {}
protected String s;
protected int n;
public Foo clone() {
return (Foo) super.clone();
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
public String getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
}
并且它在MyClass
中使用,并且处理程序被传递给两个线程A
和B
如果同时线程A尝试克隆处理程序并且线程B尝试更改处理程序的公共变量?
例如。
Foo Class
s = "Hello"
n = "42"
此课程传递给同时运行的A
和B
A
想要克隆Foo Class
,并且在1μs后B
想要将n更改为43
。
克隆结果为s = "Hello" and n = "42" || n = "43"
?
更简单:super.clone()
是线程安全的,还是我必须使用lock
或synchronized
?如果我必须使用lock
或synchronized
,这是使用它们的最佳方式吗?
答案 0 :(得分:2)
你有点滥用术语“线程安全”。它并不意味着“同步”,这显然是你如何使用它。没有多少同步可以防止实现错误破坏线程安全性。作为一个例子,你编写的任何代码在没有任何锁定的情况下改变对象的代码都会明显违反对象的线程安全性,并且没有像Object.clone
这样的库方法可以做的事情。
最终,线程安全始终掌握在实现者的手中,Object.clone()
不会做任何事情来使你更难:它只是读取当前对象的状态并将其复制到新对象。它不会发布那个新对象。
答案 1 :(得分:1)
clone
没有具体描述为线程安全,这意味着它不是。如果一个线程正在克隆该对象而另一个线程正在更改它,则克隆可能会以不一致的状态结束。
你可以在clone
函数中获取锁定,但更好的方法是在调用clone
的代码中获取它。
答案 2 :(得分:1)
如果两个线程试图在同一个Foo实例上执行此方法,那么它不是线程安全的。
您应该使用此实例创建一个互斥锁。例如,将执行此克隆方法的代码放在synchronized(fooInstance)块中。