aspose file tools*
The moose likes Threads and Synchronization and the fly likes atomicity & volatality Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "atomicity & volatality" Watch "atomicity & volatality" New topic
Author

atomicity & volatality

sarvesh meens
Ranch Hand

Joined: Mar 31, 2006
Posts: 43

Let me summarise my understanding on atomicity in java.

* Read,assignment operations on all primitive data-types except long and double are atomic.
* Read,assignment operations on references are atomic.
* Increment,decrement operations on all data-types are non-atomic.
* All operations on long and double are non-atomic.

Is any of the above stated points wrong?

Lets examine a sample program:

This class is to be used in a multi-threaded environment:

class MyData
{
int myValue = 0;

int read()
{
return myValue;
}

void set(int someOtherValue)
{
myValue = someOtherValue;
}
}

There is no need to syncronize either of the methods.

There is still scope for ambiguity.
The following actions occur in sequence:
Initial value of myValue is 0.
Thread 1 sets myValue to 10 thru set(..).
Thread 2 reads myValue. Thread 2 may still return 0.
The reason being that thread 2 might have cached myValue before it was set to 10 by Thread 1.

To discourage caching,myValue can be declared volatile.
According to literature on net,even volatile cannot ensure that there will never be any mis-match.
Is this true?
What if myValue is of type long or double?
Will making 'value' volatile ensure that there will be no corruption?
Or should read() and set(..) be syncronized to prevent corruption?
i.e

class MyData
{
long myValue = 0;

//should this be really syncronized?
syncronzied long read()
{
return myValue;
}

//should this be really syncronized?
syncronzied void set(int someOtherValue)
{
myValue = someOtherValue;
}
}

Looking forward to some enlightenment !!
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

Hi,

Welcome to JavaRanch!

First, a bit of business: you may not have read our naming policy on the way in. It requires that you use a full, real (sounding) first and last name for your display name. Funny "handles" aren't acceptable here. You can change your display name here. Thanks!

As to your questions: sounds like your understanding of the issues is very good. And for the last part: yes, they should be synchronized.


[Jess in Action][AskingGoodQuestions]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Cheetha]: Is any of the above stated points wrong?

They appear correct, assuming that you are not talking about fields which have been declared volatile. Read and write on volatile long and double fields were always supposed to be atomic, according to specs. In actuality there were often not atomic for earlier versions of Java; I believe this was fixed by JDK 1.4. Or more definitely by JDK 5.

[Cheetha]: There is no need to syncronize either of the methods.

Well, aside from the possibility of some threads seeing old data, which you address in subsequent comments.

[Cheetha]: According to literature on net,even volatile cannot ensure that there will never be any mis-match.
Is this true?


I'm not sure what you mean by mis-match. Volatile definitely forces a fresh read or write of the data to main memory, same as synchronization. The literature you refer to could refer to the old problem of non-atomic longs and doubles. Or it could refer to the fact that the atomicity given by volatile is often too low-level for more complex operations that require synchronization to cover several consecutive actions.

Neither of these concerns seems to apply to the code shown - the two methods you've got do not use long or double, and do not contain anything more complex than a single read, or a single write. So volatile ought to provide all the thread-safety you might expect for a simple getter or setter. Meaning you can still get in trouble if you want to do a get followed by a set, because another thread might change the value in between. But you'd have a similar problem with synchronization, after all, if you did want to do a more complex operation in a thread-safe manner. You'd need external synchronization. Or a new method to handle the more complex operation. Check out [url=AtomicInteger]AtomicLong[/url] for examples of more complex operations that you might need to be atomic, like compareAndSet() or getAndIncrement().

[Cheetha]: Will making 'value' volatile ensure that there will be no corruption?
Or should read() and set(..) be syncronized to prevent corruption?


For the particular methods shown, I'm pretty sure volatile and synchronized would have the same effect. Values seen by all threads would be up-to-date, and the only way you'd get "corruption" would be if you need to combine two or more method calls for more complex actions.


"I'm not back." - Bill Harding, Twister
sarvesh meens
Ranch Hand

Joined: Mar 31, 2006
Posts: 43

I apologise for violating naming policy.

Ernest,Jim thanks a lot for your opinions.

Got some doubt about the last point you made by Jim.

For the particular methods shown, I'm pretty sure volatile and synchronized would have the same effect.


I dont understand how making the long value volatile can prevent data corruption.

Sample scenario:

Am using a 32-bit processor.
long is 64 bits.

Thread 1 reads the myValue.
Thread 2 sets the myValue.

read on long occurs in the following sequence:
//the sequence depends on processor
operation R1 : read first 32 bits
operation R2 : read last 32 bits


Set on long contains the following operations:
//the sequence depends on processor
operation S1 : set first 32 bits
operation S2 : set last 32 bits

since the myValue is volatile,all these operations occur in RAM and nothing is cached.

Thread 1 completes R1. (reads old value)
Thread 2 completes S1. (sets new value)
Thread 2 completes S2. (//for some reason,thread2 is offered two time slices)
Thread 1 completes R2. (reads new value)

By the end of the above sequence,
Thread 1 would have read corrupted value.

Here,making the long variable volatile is not preventing corruption.

Let me know if the above explained sequence can work in anyother way.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Thanks for changing your name; unfortunately your name still doesn't comply with the naming policy. We need a first and last name. Thanks.

As for your question: the Java specs simply forbid longs and doubles from being split up that way, if we're talking about a field which has been declared volatile. See Non-atomic Treatment of double and long 17.8. If thread 1 executes R1, thread 2 is not allowed to execute S1 or S2 until thread 1 completes R2. As I said earlier, this has always been forbidden by the specs for volatile variables, but up until JDK 1.4 it still happened; it was a common bug. Nowadays it's been fixed.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: atomicity & volatality