有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

考虑类中的一个片段:

    // 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) 个答案

  1. # 1 楼答案

    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

    In a multithreaded use-case , can the object p be considered as published safely from the showPoints() or showNextPoint() ? What conditions must hold true in show() for this ?

    这完全取决于您如何编写代码以及合同是什么。如果一个方法对一个对象进行了更改,那么它应该被记录下来。如果调用方不希望这样做,那么您应该传入该方法可以“拥有”的Point对象的副本,或者该方法本身应该复制Point本身

    同步对象更改的复杂性是许多Java对象不可变的原因之一。你可以考虑这样做{{CD10}}。使xy值不能更改,这意味着show方法及其生成的任何线程都可以安全地使用参数,而不必担心调用方对其进行更改

    编辑:

    If show(Point p) is guaranteed 1) not to start a new thread and 2) not to change p's state , can the showPoints() method be considered as safely publishing p ?

    @JohnVint对此有一些更好的观点,但我想我会补充我的想法。我不知道你在问什么,也不知道你认为“安全出版”意味着什么。魔鬼在于细节。如果show()没有启动新线程,那么是的,您发布的代码将起作用,可以使用相同的可变Point对象

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