Tom Hobbs wrote:
Yes, you're right.

I knew about the non-atomicity of ++, my concern was a call to reset
creeping in between the two parts of that operation.

That is a very good point.

Leaving reset unsynchronized, even with volatile, would lead to results that would not be possible with full synchronization. Suppose thread A is going to do a reset, and thread B is going to do an increment, and everybody agrees the count is currently 10.

With synchronization, after both operations have completed, count is either 1 (A:reset, B:increment) or 0 (B:increment, A:reset).

With only increment synchronized, even if the the count is volatile, we add the possible outcome 11, which cannot be reached by executing the two methods atomically:

B: volatile read, result 10
A: volatile write of 0
B: volatile write of 11

I think it is best to stick to synchronization and the java.util.concurrent classes, ignoring volatile, except in really important performance-critical situations. If we do find we need to use volatile, I would like to take the time to do a formal proof-of-correctness based on the JLS rules.

I forgot about the "Get a global lock on the variable" that volatile
would require as mentioned here;
http://www.javaperformancetuning.com/news/qotm051.shtml

I don't think we can depend on anything other than the JLS, or possibly "Java Concurrency in Practice" which seems to tend towards safety if it simplifies the situation at all.

For example, I would be surprised if a SPARC v.9 TSO implementation of volatile needed to do more than a "membar #StoreLoad" between a store to a volatile variable and the next load of anything. Even on a system that needed to do more, any locking would treat the volatile read and the volatile write of the ++ as two separate operations.

Patricia

Reply via email to