考虑一个类的片段:
// tail call to show
void showNextPoint(){
Point p = new Point();
p.x = 10;
p.y = 12;
show(p);
}
// multiple calls to show
void showPoints(){
Point p = new Point();
p.x = 10; p.y = 12;
show(p);
p.x = 20; p.y = 22;
show(p);
p.x = 30; p.y = 32;
show(p);
}
void show(Point p){
// use p in some way
// can p's state be changed safely ?
// can a new thread be started to work with p safely ?
}
在多线程用例中,对象p
是否可以被视为从showPoints()
或showNextPoint()
安全发布? show()
对此有什么条件?
如果保证show(Point p)
1)不开始新线程和2)不更改p状态,showPoints()
方法是否可以被视为安全发布p
?
答案 0 :(得分:3)
show()
方法获得对Point p
的引用。如果调用者之后对p
进行了更改,则会对相同的对象进行更改。如果show()
以任何方式更改p
,那么它将更新调用方正在使用的相同p
对象。如果分叉的线程具有此p
,那么您就会以哪种顺序执行p
更新的竞争条件。
Point p = new Point(1, 2);
show(p);
// p.x == 100 here
void show(Point p) {
p.x = 100;
}
你问:
void show(Point p){
// use p in some way
// can p's state be changed safely ?
// can a new thread be started to work with p safely ?
}
在不影响来电者的对象的情况下,不能安全地更改它,不。当内存同步发生时,新线程也不能对p
进行更改而不会影响调用者的对象。
在多线程用例中,对象p是否可以被视为从
showPoints()
或showNextPoint()
安全发布? show()中必须包含哪些条件?
这一切都取决于你如何编写代码 - 合同是什么。如果方法对对象进行更改,则应记录该对象。如果调用者不希望这样,那么你应该传入方法可以“拥有”的Point
对象的副本,或者方法本身应该复制Point
本身。
同步对象更改的复杂性是许多Java对象不可变的原因之一。您可以考虑对Point
执行此操作。这样就不能更改x
和y
值,这意味着show
方法及其生成的任何线程都可以安全地使用参数,而不必担心调用者对其进行更改
修改强>
@JohnVint对此有一些更好的观点,但我想我会添加我的想法。我不确定你在这里问什么,我不确定你认为“安全发布”意味着什么。细节决定成败。如果如果show(Point p)有保证1)不开始新线程和2)不改变p的状态,showPoints()方法是否可以被视为安全发布p?
show()
没有启动新线程,那么是,您发布的代码将起作用,并且可以使用相同的可变Point
对象。
任何采用对象参数但不以任何方式更改对象的方法都可以说它是“安全地使用”(我猜)对象。由于showPoints()
构造了对象并且只有对它的引用,因此这当然也是安全的。这是p
被修改的时候,还有另一个线程涉及到一切都在变化。