redundant volatile in cheap read-write lock? - java

Brian Goetz in his article from https://www.ibm.com/developerworks/java/library/j-jtp06197/
uses the example pasted below as a cheap read-write lock. My question is that if the int variable value is not declared volatile then would it make a difference? My understanding is that since the writes to value are done within a synchronized block so latest value will be visible to other threads any way and therefore declaring it volatile is redundant. Please clarify?
#ThreadSafe
public class CheesyCounter {
// Employs the cheap read-write lock trick
// All mutative operations MUST be done with the 'this' lock held
#GuardedBy("this") private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
}

My understanding is that since the writes to value are done within a synchronized block so latest value will be visible to other threads any way
This is incorrect. Generally, there is no guarantee that other threads "see" changes to variables as soon as the change is made. A thread may see a stale value for a changed variable because, e.g. the thread sees the value really in a register instead of main memory.
A volatile variable establishes "happens-before" semantics. The JLS, section 17.4.5, states:
Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
The JLS, Section 8.3.1.4:
A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4).
The reason that the field must be volatile is that even though the read is atomic, it needs to ensure that the value is current -- that any value previously written by another thread is visible. The read being atomic is not enough; volatile is still necessary to ensure consistency of the value.

public synchronized int increment()
This synchronized prevents you from skipping an increment if two threads or more were trying to increment at the same time (because ++ is not atomic).
private volatile int value
This prevents you from seeing an outdated value in one thread which was already incremented in another thread. (Note that we could also have made getValue synchronized to achieve this)

Thanks very much for the answers guys. Found this on oracle website as well now: "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."
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

Related

How stale data is avoided using synchronized keyword?

In the book "Java Concurrency in Practice", under the section, 3.1.1 State data, there is a code
#NotThreadSafe
public class MutableInteger {
private int value;
public int get() { return value; }
public void set(int value) { this.value = value; }
}
which is not thread safe,because:
if one thread calls set, other threads calling get may or may not see
that update.
whereas using synchronized keyword on both set and get methods makes it "correct". How?
#ThreadSafe
public class SynchronizedInteger {
#GuardedBy("this") private int value;
public synchronized int get() { return value; }
public synchronized void set(int value) { this.value = value; }
}
Here too if value is 0, and Thread A has called set(2) while Thread B has called get(), B may get value 0 and then A will set it to 2...which previous code was already doing. So what benefit we got from synchronizing the code..
May be I am missing something, but please guide. Thank you
The issue you fix this way is not that thread B executes the set immediately after A executes a get, that one will still return the "old" (well, technically correct at the time, but soon to be wrong) value.
The issue the synchronization fixes is that even if thread B wrote before thread A read, A could read an old value due to caching (most likely CPU caches, but this depends on the JVM implementation). A non-synchronized read from a non-volatile variable can use a cached value. In other words: the synchronized creates a read-barrier, which means "you have to re-read this value, even if you already have it in your CPU cache".
Note that for this specific case, simply adding volatile to value would have the same effect, but for more complex access patterns synchronized (or it's equivalence in newer APIs Lock) is necessary.
When you use synchronized method you get the exclusive access to the object that is in "Race Condition" risks. In that case you get the exclusive access to the value.
This goal is obtained because the synchronized method use semaphore.
Synchronized in Java
Java Doc - Here you can find a good example.
From Java Doc:
If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:
First,
it is not possible for two invocations of synchronized methods on the
same object to interleave.
When one thread is executing a synchronized method for an object, all
other threads that invoke synchronized methods for the same object
block (suspend execution) until the first thread is done with the
object.
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.
It's all about the "Happens Before Relationship", as termed by the official Java documentation.
In your case of two synchronised getter & setter methods reading & writing the same instance variable respectively, it depends on the sequence of operations, ie, whether the getter or setter was called first.
This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement.
Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.
Synchronisation is one of ways to achieve this consistency. Another one, in your particular case would be to make the variable as volatile.
From the official Java docs:
Using volatile variables reduces the risk of memory consistency
errors, because any write to a volatile variable establishes a
happens-before relationship with subsequent reads of that same
variable. This means that changes to a volatile variable are always
visible to other threads.

Does function returning a volatile variable need synchronization?

setGameState() and getGameState() can be called from different threads. m_gameState is volatile so its value/change could be visible to other threads.
Question:
Do the functions need to be synchronized or does volatile on the variable suffice?
private volatile EGameState m_gameState;
public void setGameState(EGameState a_gameState) {
m_gameState = a_gameState;
}
public EGameState getGameState() {
return m_gameState;
}
Access to the volatile variable acts as though it is synchronized on itself.
Accessing a volatile variable never holds a lock, it is not suitable for cases where we want to read-update-write as an atomic operation.Here you are required to use a synchronized block.
For other cases it will suffice if you didn't use synchronization(like normal get and set)
That depends. Do you require the updates of your EGameState field to be ordered or not?
If they must be ordered, than a synchronized block (on this) is mandatory, if not, volatile is sufficient.
http://gee.cs.oswego.edu/dl/jmm/cookbook.html
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java
Is a write to a volatile a memory-barrier in Java
volatile is an automatic Load/Store Fence in memory; read and writes are atomic; you don't need to synchronize anything in your posted example.
If volatile keyword is used with variable, all threads will get latest value of the variable from main memory. Note that it does not acquire a lock so if you want to do any atomic operation, volatile is not sufficient. For atomic operations synchronized is used.In your case you are only reading the value m_gameState = a_gameState; so volatile is sufficient.
Hope it helps.

Java - how does Lock guarantee happens-before relationship?

Let's consider the following standard synchronization in Java:
public class Job {
private Lock lock = new ReentrantLock();
public void work() {
lock.lock();
try {
doLotsOfWork();
} finally {
lock.unlock();
}
}
}
I understand, based on Javadoc, that this is equivalent to synchronized block. I am struggling to see how this is actually enforced on the lower-level.
Lock has a state which is a volatile, upon call to lock() it does a volatile read, then upon release it performs a volatile write. How can a write to a state of one object ensure, that none of the instruction of doLotsOfWork, which might touch lots of different objects, will not be executed out of order?
Or imagine that doLotsOfWork is actually substituted with 1000+ lines of code. Clearly the compiler cannot know in advance that there is a volatile somewhere inside the lock, therefore it needs to stop re-ordering the instructions. So, how is happens-before guaranteed for lock/unlock, even though it is built around volatile state of a separate object?
Well, if I understood correctly then your answer is here. volatile writes and reads introduce memory barriers : LoadLoad, LoadStore, etc. that forbid re-orderings. At the CPU level this is translated to actual memory barriers like mfence or lfence (the CPU forces the non-reordering via some other mechanisms too, so you might see something else in the machine code as-well).
Here is a small example:
i = 42;
j = 53;
[StoreStore]
[LoadStore]
x = 1; // volatile store
i and j assignments can be re-ordered between then, but they can not with x=1 or in other words i and j can not go below x.
Same applies to the volatile reads.
For your example every operation inside doLotsOfWork can be re-ordered as the compiler pleases, but it can not be re-ordered with lock operations.
Also when you say that the compiler can not know that there is a volatile read/write, you are slightly wrong. It has to know that, otherwise there would be no other way to prevent those re-orderings.
Also, last note: since jdk-8 you can enforce non re-orderings via the Unsafe that provides ways to that besides volatile.
From Oracle's documentation:
A write to a volatile field happens-before every subsequent read of
that same field. Writes and reads of volatile fields have similar
memory consistency effects as entering and exiting monitors, but do
not entail mutual exclusion locking.
Java Concurrency in Practice states it even more clearly:
The visibility effects of volatile variables extend beyond the value
of the volatile variable itself. When a thread A writes to a volatile
variable and subsequently thread B reads that same variable, the
values of all variables that were visible to A prior to writing to the
volatile variable become visible to B after reading the volatile
variable.
Applied to ReentrantLock it means that everything executed before lock.unlock() (doLotsOfWork() in your case) will be guaranteed to happen before subsequent call to lock.lock(). Instructions inside doLotsOfWork() still can be reordered among themselves. The only thing that is guaranteed here is that any thread which will subsequently acquire the lock calling lock.lock() will see all changes done in doLotsOfWork() before calling lock.unlock().

How to write a simple thread-safe class using a volatile variable?

I want to write a simple thread-safe class that could be used to set or get an Integer value.
The easiest way is to use the synchronized keyword:
public class MyIntegerHolder {
private Integer value;
synchronized public Integer getValue() {
return value;
}
synchronized public void setValue(Integer value) {
this.value = value;
}
}
I could also try using volatile:
public class MyIntegerHolder {
private volatile Integer value;
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
}
Is the class with the volatile keyword thread-safe?
Consider the following sequence of events:
Thread A sets the value to 5.
Thread B sets the value to 7.
Thread C reads the value.
It follows from the Java Language Specification that
"1" happens-before "3"
"2" happens-before "3"
but I don't see how it could follow from the specification that "1" happens-before "2" so I suspect that "1" doesn't happen-before "2".
I suspect the thread C may read 7 or 5. I think the class with the volatile keyword is not thread-safe and the following sequence is also possible:
Thread A sets the value to 5.
Thread B sets the value to 7.
Thread C reads 7.
Thread D reads 5.
Thread C reads 7.
Thread D reads 5.
...
Am I correct in assuming that MyIntegerHolder with volatile is not thread-safe?
Is it possible to make a thread-safe Integer holder by using AtomicInteger:
public class MyIntegerHolder {
private AtomicInteger atomicInteger = new AtomicInteger();
public Integer getValue() {
return atomicInteger.get();
}
public void setValue(Integer value) {
atomicInteger.set(value);
}
}
?
Here is a fragment of the Java Concurrency In Practice book:
"Reads and writes of atomic variables have the same memory semantics
as volatile variables."
What is the best (preferably non-blocking) way of writing a thread-safe MyIntegerHolder?
If you know the answer, I would like to know why you think it is correct. Does it follow from the specification? If so, how?
The keyword synchronized is saying that if Thread A and Thread B want to access the Integer, they cannot do so simultaneously. A is telling B wait until I'm done with it.
On the other hand, volatile makes threads more "friendly". They start talking to each other and working together to perform tasks. So when B tries to access, A will inform B of everything it has done until that moment. B is now aware of the changes and can continue its job from where A left of.
In Java, you have Atomic for this reason, which under the covers use the volatile keyword, so they are doing pretty much the same thing, but they save you time and effort.
The thing you are looking for is AtomicInteger, you are right about this. For the operation you are trying to perform this is the best choice.
There are two main uses of `AtomicInteger`:
* As an atomic counter (incrementAndGet(), etc) that can be used by many threads concurrently
* As a primitive that supports compare-and-swap instruction (compareAndSet()) to implement non-blocking algorithms.
To answer your question on a general note
It depends on what you need. I'm not saying synchronized is wrong and volatile is good, otherwise the nice Java people would have removed synchronized a long time ago. There is no absolute answer, there are a lot of specific cases and usage scenarios.
A few of my bookmarks:
Concurrency tips
Core Java Concurrency
Java concurrency
Update
From the Java Concurrency specification available here:
Package java.util.concurrent.atomic
A small toolkit of classes that support lock-free thread-safe
programming on single variables.
Instances of classes `AtomicBoolean`, `AtomicInteger`, `AtomicLong`, and `AtomicReference` each provide access and updates to a single variable of the corresponding type.
Each class also provides appropriate utility methods for that type.
For example, classes `AtomicLong` and AtomicInteger provide atomic increment methods.
The memory effects for accesses and updates of atomics generally follow the rules for volatiles:
get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.
Also from Here
The Java programming language volatile keyword:
(In all versions of Java) There is a global ordering on the reads and writes to a volatile variable. This implies that every thread accessing a volatile field will read its current value before continuing, instead of (potentially) using a cached value. (However, there is no guarantee about the relative ordering of volatile reads and writes with regular reads and writes, meaning that it's generally not a useful threading construct.)
If you need only get / set on a variable it is enough to declare it volatile like you did. If you check how AtomicInteger set / get work you will see the same implementation
private volatile int value;
...
public final int get() {
return value;
}
public final void set(int newValue) {
value = newValue;
}
but you cannot increment a volatile field atomically this simple. This is where we use AtomicInteger.incrementAndGet or getAndIncrement methods .
Chapter 17 of the Java Language Specification defines the happens-before relation on memory operations such as reads and writes of shared variables. The results of a write by one thread are guaranteed to be visible to a read by another thread only if the write operation happens-before the read operation.
The synchronized and volatile constructs, as well as the Thread.start() and Thread.join() methods, can form happens-before
relationships. In particular: Each action in a thread happens-before
every action in that thread that comes later in the program's order.
An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method
entry) of that same monitor. And because the happens-before relation
is transitive, all actions of a thread prior to unlocking
happen-before all actions subsequent to any thread locking that
monitor.
A write to a volatile field happens-before every subsequent read of that same field. Writes and reads of volatile fields have similar
memory consistency effects as entering and exiting monitors, but do
not entail mutual exclusion locking.
A call to start on a thread happens-before any action in the started thread.
All actions in a thread happen-before any other thread successfully returns from a join on that thread.
reference: http://developer.android.com/reference/java/util/concurrent/package-summary.html
from my understanding 3 means: if you write (not based read result) / read is fine. if you write (based on read result, e.g., increment) / read is not fine. Since volatile "do not entail mutual exclusion locking"
Your MyIntegerHolder with volatile is thread safe. But AtomicInteger is preferred if you are doing concurrent program, because it also provides a lot of atomic operations.
Consider the following sequence of events:
Thread A sets the value to 5.
Thread B sets the value to 7.
Thread C reads the value.
It follows from the Java Language Specification that
"1" happens-before "3"
"2" happens-before "3"
but I don't see how it could follow from the specification that "1"
happens-before "2" so I suspect that "1"
doesn't happen-before "2".
I suspect the thread C may read 7 or 5. I think the class with the
volatile keyword is not thread-safe
You are right here that "1" happens-before "3" and "2" happens-before "3". "1" does not happens-before "2", but it doesn't mean that it is not Thread-safe. The thing is that the example you provided is ambiguous. If you are saying "sets the value to 5", "sets the value to 7", "reads the value" happens sequentially, you can always read the value of 7. And it is nonsense to put them in different threads. But if you are saying that 3 threads executes concurrently without sequence, you can even get value of 0, because "reads the value" could happen first. But this is nothing with Thread-safe, there is no order expecting from the 3 actions.
The question was not easy for me, because I thought (incorrectly) that knowing everything about the happens-before relation gives one a complete understanding of the Java Memory Model - and the semantics of volatile.
I found the best explanation in this document:
"JSR-133: JavaTM Memory Model and Thread Specification"
The most relevant fragment of the above document is the section "7.3 Well-Formed Executions".
The Java Memory Model guarantees that all executions of a program are well-formed. An execution is well-formed only if it
Obeys happens-before consistency
Obeys synchronization-order consistency
... (some other conditions must also be true)
Happens-before consistency is usually enough to come to a conclusion about the program behavior - but not in this case, because a volatile write doesn't happen-before another volatile write.
The MyIntegerHolder with volatile is thread-safe, but it's safety comes from the synchronization-order consistency.
In my opinion when Thread B is about to set the value to 7, A doesn't inform B of everything it has done until that moment (as one of the other answers suggested) - it only informs B about the value of the volatile variable. Thread A would inform B about everything (assigning values to other variables) if the action taken by Thread B was read and not write (in that case, there would exist the happens-before relationship between the actions taken by these two threads).

volatile synchronized combination for performance

When Synchronization is used there is a performance impact. Can volatile be used in combination with synchronized to reduce the performance overhead ? For example, instance of Counter will be shared among many threads and each thread can access Counter's public methods. In the below code volatile is used for getter and synchronized is used for setter
public class Counter
{
private volatile int count;
public Counter()
{
count = 0;
}
public int getCount()
{
return count;
}
public synchronized void increment()
{
++count;
}
}
Please let me know in which scenario this might break ?
Yes, you definitely can. In fact, if you look at the source code of AtomicInteger, it's essentially what they do. AtomicInteger.get simply returns value, which is a volatile int (link). The only real difference from what you've done and what they do is that they use a CAS for the increment instead of synchronization. On modern hardware, a CAS can eliminate any mutual exclusion; on older hardware, the JVM will put some sort of mutex around the increment.
Volatile reads are about as fast as non-volatile ones, so the reads will be quite fast.
Not only that, but volatile fields are guaranteed not to tear: see JLS 17.7, which specifies that volatile longs and doubles are not subject to word tearing. So your code would work with a long just as well as an int.
As Diego Frehner points out, you might not see the result of an increment if you get the value "right as" the increment happens -- you'll either see the before or the after. Of course, if get were synchronized you'd have exactly the same behavior from the read thread -- you'd either see the before-increment or post-increment value. So it's really the same either way. In other words, it doesn't make sense to say that you won't see the value as it's happening -- unless you meant word tearing, which (a) you won't get and (b) you would never want.
1. I have personally used this mechanism of volatile combined with synchronized.
2. You can alone use synchronized, and you will always get a consistent result, but using
only volatile alone will Not yield the same result always.
3. This is because volatile keyword is not a synchronization primitive. It merely prevents caching of the value on the thread, but it does not prevent two threads from modifying the same value and writing it back concurrently.
4. volatile give concurrent access to threads without lock, but then using synchronized will allow only one thread to get access to this and all the synchronized methods in the class.
5. And using both volatile and synchronized will do this....
volatile - will reflect the changed values to thread, and prevent caching,
synchronized - But using synchronized keyword, will make sure that only one thread gets the access to the synchronized methods of the class.
You will not always get the most actual count when calling getCount(). An AtomicInteger could be appropriate for you.
There wouldn't be a performance gain from using both. Volatile guarantees that the value of a variable will be consistent when reading/writing to the variable across threads executing in parallel by preventing caching. Synchronized, when applied to a method (as you do in your example), only allows a single thread to enter that method at a time and blocks others until execution is complete.

Categories

Resources