使用java中的方法限制安全发布

时间:2012-03-07 12:30:28

标签: java multithreading

考虑一个类的片段:

    // 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

1 个答案:

答案 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执行此操作。这样就不能更改xy值,这意味着show方法及其生成的任何线程都可以安全地使用参数,而不必担心调用者对其进行更改

修改

  

如果show(Point p)有保证1)不开始新线程和2)不改变p的状态,showPoints()方法是否可以被视为安全发布p?

@JohnVint对此有一些更好的观点,但我想我会添加我的想法。我不确定你在这里问什么,我不确定你认为“安全发布”意味着什么。细节决定成败。如果show()没有启动新线程,那么是,您发布的代码将起作用,并且可以使用相同的可变Point对象。

任何采用对象参数但不以任何方式更改对象的方法都可以说它是“安全地使用”(我猜)对象。由于showPoints()构造了对象并且只有对它的引用,因此这当然也是安全的。这是p被修改的时候,还有另一个线程涉及到一切都在变化。