Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will all java threads see shared resource updates after modification in synchronized method?

Is it necessary to use specialized concurrent versions of Java's Collections data structures (e.g. CopyOnWriteArrayList vs ArrayList) if all access to a pair of data structures is always wrapped with the acquisition and release of a lock (in particular, using a static synchronized method for any modifications to the data structure). For example:

public static synchronized Item doIt() {
    // remove something from data structure 1
    // add the removed item to data structure 2
    // return removed item
}

I know the synchronized method will enforce only one thread at a time performing the updates, but by the time a thread has exited the method, are the other threads guaranteed to see the updated data structures, or do I still need specialized concurrent data structures for that guarantee?

Edit:

Here's a better example of what I'm trying to do:

private static final List<Item> A;
private static final HashMap<Integer,Item> B;

public static Item doSomething() {
    // some stuff ...
    Item item = doIt();
    // some other stuff ...
    return item;
}

private static synchronized Item doIt() {
    Item theItem = A.remove( A.size()-1 );
    B.put( theItem.getId(), theItem );
    return theItem;
}
like image 744
RTF Avatar asked Aug 05 '14 15:08

RTF


2 Answers

Yes, if the access is always wrapped in synchronized methods/blocks.

This is because, synchronized establishes a happens-before relation between synchronized methods/blocks (on the same object). Quoting from Synchronized Methods in the Java Tutorial:

Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

However, it is important that you really wrap all access in synchronized blocks. If you would, for example, return a reference to the list from a synchronized method like this

public synchronized List<Object> GetList() {
    return this.myList;
}

and use the list outside the synchronized method, you will not get that guarantee!

like image 84
Simon Lehmann Avatar answered Oct 07 '22 16:10

Simon Lehmann


Synchronization is about quite a bit more than just mutual exclusion. Namely, it is about the visibility of all actions which go on within the block (and precede it as well) to any other thread which subsequently acquires the same lock.

Therefore you don't need concurrent data structures when you use locking for all access to the structures.

Finally, just to make sure: you must use locking for all access, including all reads.

like image 29
William F. Jameson Avatar answered Oct 07 '22 15:10

William F. Jameson