Atomic Access and Assignment

Variables shared between multiple threads (e.g., instance variables of objects) have atomic assignment guaranteed by the Java language specification for all data types except for longs and doubles. Actually, the storing of a value into a variable takes two primitive operations, a store and a write. However, the language specification also states that once a store operation occurs on a particular variable, no other store operation is allowed on that variable until the write operation has occurred. The specification allows longs and doubles to be stored in two separate sets of store+write operations, hence their exception to atomicity. A similar atomic specification applies for reading variables.

This means that access and update of variables are automatically synchronized (as long as they are not longs or doubles). If a method consists solely of a variable access or assignment, there is no need to make it synchronized for thread safety, and every reason not to do so for performance. Thread safety extends further to any set of statements that are accessing or assigning to a variable independently of any other variable values. The exclusion here precludes setting a variable that depends on the value of another variable as being thread-safe; this would be two separate operations, which is inherently not thread-safe. For example:

public void setMe(Object o) {me = o;}
public Object getMe( ) {return me;}

are thread-safe methods, with no need for synchronized modifiers to be added to the method declaration. On the other hand:

public void setMe(Object o) {if(overwrite) me = o;}

is not thread-safe: overwrite may be true at the time of checking in the if statement, but false by the time of the subsequent assignment statement. Anything more complex than simple assignments and accesses is probably not thread-safe: it depends on whether any particular intermediate state that can be accessed is considered corrupt by the application. Consider the code being halted before or after any particular atomic statement, and decide whether or not another thread could now access a corrupt application state.

Combining several calls to methods that atomically assign variables is the same problem as combining several calls to synchronized methods. The individual calls are executed atomically, but the combination is not necessarily atomic:

public void setMe1(Object o) {me = o;}
public void setMe2(Object o) {me = o;}
public void setBoth(Object o1, Object o2) {setMe1(o1);setMe2(o2);}

For these three methods, it does not matter whether setMe1() and setMe2( ) are synchronized or not. setBoth( ) is not synchronized, so it can be interrupted between the calls to setMe1( ) and setMe2( ), allowing another thread to update one of the instance variables. This can leave the object in a potentially corrupt application state if both instance variables are always supposed to be updated together. Specifically, if two threads call the setBoth( ) method simultaneously, the outcome is not predictable unless setBoth( ) is synchronized.

A longer discussion about Java’s atomicity can be found in an article by Art Jolin,[70] where he discusses unsynchronized thread-safe data structures, including why a binary tree (specifically the AWTEventMulticaster class) can be thread-safe without any synchronized methods.



[70] “Java’s Atomic Assignment,” Java Report, August 1998.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.196.217