Acquiring multiple atomic locks in java

I have the following code: Note. I have simplified the code as much as possible for readability. If I forget any critical parts, let me know.

public class User(){

    private Relations relations;

    public User(){
        relations = new Relations(this);
    }   

    public getRelations(){
        return relations;
    }
}


public class Relations(){

    private User user;

    public Relations(User user){
        this.user = user;
    }

    public synchronized void setRelation(User user2){
        Relations relations2 = user2.getRelations();

        synchronized(relations2){

            storeRelation(user2);

            if(!relations2.hasRelation(user))
                relations2.setRelation(user);
        }
    }   

    public synchronized boolean hasRelation(User user2){
        ... // Checks if this relation is present in some kind of collection
    }

    /*Store this relation, unless it is already present*/
    private void storeRelation(User user2){
        ... // Stores this relation in some kind of collection
    }
}

This implementation should make sure that for all x, y relations with:

x.user = u_x
y.user = u_y

the following invariant holds:

x.hasRelation( u_y ) <=> y.hasRelation( u_x )

I believe this is true for the code above?

Note. Of course, it is not executed at the time setRelation (..) is executed, but at this moment the locks for both interconnected ones are held by the executing thread, so that no other thread can read hasRelation (..) of one of the corresponding relations.

, , , - . ? , ? , setRelation (..) - .

+4
1

: ( , .., , if(!relations.hasRelation(user)) relations2.setRelation(user2); if(!relations2.hasRelation(user)) relations2.setRelation(user);), : x, y, y, x, , .

- Relations. , lockOrder:

private final int lockOrder;

currentLockOrder:

private static int currentLockOrder = 0;

, Relations, lockOrder currentLockOrder :

public Relations()
{
    synchronized(Relations.class) // a lock on currentLockOrder
    {
        lockOrder = currentLockOrder;
        ++currentLockOrder;
    }
}

Relations , lockOrder. setRelation :

public void setRelation(final User thatUser)
{
    final Relations that = thatUser.getRelations();

    synchronized(lockOrder < that.lockOrder ? this : that)
    {
        synchronized(lockOrder < that.lockOrder ? that : this)
        {
            storeRelation(thatUser);

            if(! that.hasRelation(user))
                that.storeRelation(user);
        }
    }
}

, x, y, x, y, , .

, setRelation storeRelation. setRelation , ?

, , : x.setRelation(u_y) x.storeRelation(u_y) , y.setRelation(u_x) ( y.storeRelation(u_x)), y ? . , , . ( Relations.storeRelation(...), , .)

+8

All Articles