I am interested in the situation where one thread is waiting for change of a variable in the while loop:
while (myFlag == false) {
// do smth
}
It is repeating an infinite number of times.
In the meantime, another thread have changed the value of this variable:
myFlag = true;
Can the reader-thread see the result of changing the value of the variable in the other thread if this variable is NOT volatile? In general, as I understand it will never happen. Or am I wrong? Then when and under what circumstances, the first thread can see the change in the variable and exit the loop? Is this possible without using volatile keyword? Does size of processor's cache play role in this situation?
Please explain and help me understand! Thank you in advance!!
Can the reader-thread see the result of changing the value of the variable in the other thread if this variable is NOT volatile?
It may be able to, yes. It's just that it won't definitely see the change.
In general, as I understand it will never happen.
No, that's not the case.
You're writing to a variable and then reading from it in a different thread. Whether or not you see it will depend on the exact processor and memory architecture involved. Without any memory barriers involved, you aren't guaranteed to see the new value - but you're certainly not guaranteed not to see it either.
Can the reader-thread see the result of changing the value of the variable in the other thread if this variable is NOT volatile?
I'd like to expand a bit on #Jon's excellent answer.
The Java memory model says that all memory in a particular thread will be updated if it crosses any memory barrier. Read barriers cause all cached memory in a particular thread to be updated from central memory and write barriers cause local thread changes to be written to central.
So if your thread that writes to another volatile field or enters a synchronized block it will cause your flag to be updated in central memory. If the reading thread reads from another volatile field or enters a synchronized block in the // do smth section after the update has happened, it will see the update. You just can't rely on when this will happen or if the order of write/read happens appropriately. If your thread doesn't have other memory synchronization points then it may never happen.
Edit:
Given the discussion below, which I've had a couple times now in various different questions, I thought I might expand more on my answer. There is a big difference between the guarantees provided by the Java language and its memory-model and the reality of JVM implementations. The JLS and JMM define memory-barriers and talk about "happens-before" guarantees only between volatile reads and writes on the same field and synchronized locks on the same object.
However, on all architectures that I've heard of, the implementation of the memory barriers that enforce the memory synchronization are not field or object specific. When a read is done on a volatile field and the read-barrier is crossed on a specific thread, it will be updated with all of central memory, not just the particular volatile field in question. This is the same for volatile writes. After a write is made to a volatile field, all updates from the local thread are written to central memory, not just the field. What the JLS does guarantee is that instructions cannot be reordered past the volatile access.
So, if thread-A has written to a volatile field then all updates, even those not marked as volatile will have been written to central memory. After this operation has completed, if thread-B then reads from a different volatile field, he will see all of thread-A's updates, even those not marked as volatile. Again, there is no guarantees around the timing of these events but if they happen in that order then the two threads will be updated.
Related
Is the volatile modifier required when working with locks to guarantee memory visibility?
Trying to fully understand concurrency, memory visibility and execution control I came across several sources saying that variables updated in synchronized blocks do not require the field to be volatile (mostly no sources given and actually one page saying synchronized methods and volatility fields need to be used in conjunction).
When approaching the jls chapter 17.4.5 I found:
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.
Is this the section which says that subsequent synchronized method calls guarding the same variable variable will ensure it to be visible to the second thread? If this is the case does the same hold true for locks since we can also guarantee an order?
On the other hand what happens when suddenly we have write locks allowing 2 threads to access the field. Does the entire construct collapse and threads are never guaranteed to updated their cache even in the event if the variable is unlocked?
In short code
int field; //volatile not needed because we have a definite happens-before relationship
Lock lock;
void update(){
//No matter how many threads access this method they will always have
//the most up to date field value to work with.
lock.lock()
field *= 2;
lock.unlock();
}
From the API documentation for Lock:
https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/locks/Lock.html
All Lock implementations must enforce the same memory synchronization
semantics as provided by the built-in monitor lock, as described in
Chapter 17 of The Java™ Language Specification:
A successful lock operation has the same memory synchronization effects as a successful Lock action.
A successful unlock operation has the same memory synchronization effects as a successful Unlock action.
Unsuccessful locking and unlocking operations, and reentrant
locking/unlocking operations, do not require any memory
synchronization effects.
That's a little unclear imo but the gist of it is that yes, Lock is required to work the same way as a monitor (what the synchronized keyword does) and therefore your example does always make the most recent update of field visible without explicitly using the volatile keyword.
P.S. Get Brian Goetz's Java Concurrency in Practice, it explains all of this stuff in a lot more detail. It's basically the bible of all things concurrency in Java.
...and actually one page saying synchronized methods and volatility fields need to be used in conjunction.
You can distill everything you need to know about memory visibility and synchronized blocks down to one simple rule. That is, whatever thread A does to shared variables and objects before it exits from a synchronized (o) {...} block is guaranteed to become visible to thread B by the time thread B enters a synchronized (o) {...} block for the same object, o.
And, as #markspace already said, any implementation of java.util.concurrent.locks.Lock is required to work in the same way.
Is the volatile modifier required when working with locks to guarantee memory visibility?
volatile variable only guarantees memory visibility but not the atomicity. This is one of the main difference between volatile and the synchronized block in Java. So when you use synchronized blocks, variables do not have to be volatile. But If your variable is volatile and performing any compound actions on that variable, then you need to guard the update to the volatile variable with the lock.
Is this the section which says that subsequent synchronized method calls guarding the same variable will ensure it to be visible to the second thread? If this is the case does the same hold true for locks since we can also guarantee an order?
Yes. Because locks will give you both visibility and atomicity.
On the other hand what happens when suddenly we have write locks allowing 2 threads to access the field. Does the entire construct collapse and threads are never guaranteed to updated their cache even in the event if the variable is unlocked?
If you guarding the update to the variable on the same lock only one thread can work on that variable at any given time. So it guarantees consistency. But If you use different locks every time to guard that variable, then more than one thread will modify the variable state and can potentially make the variable state inconsistent. So, in this case, both visibility and atomicity are guaranteed but still, it can lead to inconsistency.
A strange thing. Code below works, if the condition desiredHealth < p.getFakeHealth() is true, it DOES SOMETHING.
#Override
public void run(){
while(game_running){
System.out.println("asd");
if(desiredHealth < player.getFakeHealth()){
DOES SOMETHING
}
}
BUT... without 'System.out' it does not work. It doesn't check the condition.
It is somehow on lower priority, or something.
#Override
public void run(){
while(game_running){
if(desiredHealth < player.getFakeHealth())
DOES SOMETHING
}
}
I'm new to threads, so please, dont shout at me :)
Just for info, this thread is a normal class which 'extends Thread' and yes - it is running. Also 'game_running' is true all the time.
the variable must be volatile because the volatile keyword indicates that a value may change between different accesses, even if it does not appear to be modified.
So, be sure game_running is declared volatile.
Explanation:
Ahh, I have seen this on an older SO question. I'm gonna try to find it for further information.
Your problem is happening because the output stream's print is blocking the current thread and one of the desiredHealth and player.getFakeHealth() expressions get a second chance to be evaluated/changed by other thread and voilà! Magic happens. This is because printf on glibc is synchronized, so when you print, the rest of the operations are waiting for the println operation to complete.
Resolution:
We don't have enough context(who is initializing the player, who does the changes and so on), but it's obvious that you have a threading issue, something is not properly synchronized and your background thread works with bad values. One of the reasons might be that some variables are not volatile and if your background thread reads a cached value, you already have a problem.
One of the topics you need to study regarding concurrency is the Java memory model (that's the official spec but I suggest you read a tutorial or a good book, as the spec is rather complicated for beginners).
One of the issues when different threads work with the same memory (use the same variable - e.g. when one is writing into a variable, the other makes decisions based on their value) is that for optimization reasons, the values written by one thread are not always seen by the other.
For example, one thread could run on one CPU, and that variable is loaded into a register in that CPU. If it needed to write it back to main memory all the time, it would slow processing. So it manipulates it in that register, and only writes it back to memory when it's necessary. But what if another thread is expecting to see the values the first thread is writing?
In that case, it won't see them until they are written back, which may never happen.
There are several ways to ensure that write operations are "committed" to memory before another thread needs to use them. One is to use synchronization, another is to use the volatile keyword.
System.out.println() in fact includes a synchronized operation, so it may cause such variables to be committed to memory, and thus enable the thread to see the updated value.
Declaring the variable as volatile means that any changes in it are seen by all the other threads immediately. So using volatile variables is also a way of ensuring that they are seen.
The variable that is used to decide whether to keep the thread running should normally be declared volatile. But also, in your case, the variables desiredHealth (if it's written by a different thread) and whatever variables getFakeHealth() relies on (if they are written by a different thread) should be volatile or otherwise synchronized.
The bottom line is that whatever information is shared between two threads needs to be synchronized or at the very least use volatile. Information that is not shared can be left alone.
I understand that synchronization can be used to enforce variable visibility being updated by more than one thread. i.e. Suppose we have an variable shared by two threads. If we update it in one thread, the other one is not guaranteed to see the newly updated value unless we properly synchronize the access to this variable.
But I want to know what happened under the cover to cause this. Can someone let me know?
Many thanks.
There are many other way to ensure visibility such as volatile, ordered/lazy set.
When you enter a synchronized block it performs a read barrier. This means all reads after it will be consistent. When you exit a synchronized block it performs a write barrier. This ensures that all writes are in a consistent order. The actual details of how this is done is determined by the CPU, but for x86/x64 it is a single machine code instruction or prefix.
This issue occurs on multi-processor CPU's. If the variable is not volatile, the JIT compiler will optimize its use to be kept in cache or in the registers of each cpu core separately. Threads running simultaneously on other cores will not see changes to the variable until it's saved to RAM or the cache is flushed.
If you write to a volatile variable or another synchronisation, all CPU caches are flushed immediately.
I had a code like this:
if(!flag) {
synchronized(lock) {
lock.wait(1000);
}
}
if(!flag) { print("Error flag not set!"); }
And:
void f() {
flag = true;
synchronized(lock) {
lock.notify()
}
}
A friend of mine told me I should put flag = true inside the synchronized block:
synchronized(lock) {
flag = true;
lock.notify()
}
I do not understand why. Is it some classic example? Could someone, please, explain?
If I declare my flag volatile I then do not need putting it into the synchronized block?
As flag variable is used by multiple threads, some mechanism to ensure changes visibility must be used. This is indeed a common pattern in multithreading in general. Java memory model does not otherwise guarantee the other thread will ever see the new value of flag.
This is to allow optimizations employed by modern multiprocessor systems, where maintaining cache coherency at all times may be to costly. Memory access is usually orders of magnitute slower than other "usual" CPU operations, so modern processors go to really great lengths avoid it as much as possible. Instead, frequently accessed locations are kept in small, fast, local processor memory - a cache. Changes are only done to the cache, and flushed to the main memory at certain points. This works fine for one processor, as the memory content is not being changed by other parties, so we are guaranteed cache content reflects memory content. (Well, that's an oversimplification, but from high-level's programming point of view irrelevant, I believe). The problem is, as soon as we add another processor, independently changing the memory contents, this guarantee is lost. To mitigate this problem, various (sometimes elaborate - see e.g. here) cache coherency protocols were devised. Unsurprisingly, they require some bookkeeping and interprocessor communication overhead, though.
Other, somewhat related issue is atomicity of write operations. Basically, even if the change is seen by other threads, it may be seen partially. This is not usually so much of a problem in java, as the language specification guarantees atomicity of all writes. Still, writes to 64-bit primitives (long and double) are explicitly said to be treated as two separate, 32-bit writes:
For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write. (JLS 17.7)
Back to the code in question... synchronization is required, and synchronized block satisfies the need. Still, I find making the flags like that volatile more pleasant solution. Net effect is the same - visibility guarantee and atomic write - but it doesn't clutter the code with small synchronized blocks.
Main memory is slow. Really slow. The internal cache in your CPU today is about 1000 times faster. For this reason, modern code tries to keep as much data as possible in the CPU's cache.
One of the reasons why main memory is so slow is that it's shared. When you update the main memory, all CPU cores are notified of the change. Caches, on the other hand, are per core. That means when thread A updates the flag, it just updates its own cache. Other threads might or might not see the change.
There are two ways to ensure the flag is written to main memory:
Put it in a synchronized block
Declare it volatile
volatile has the advantage that any access to the flag will make sure the state of the flag in main memory is updated. Use this when you use the flag in many places.
In your case, you already have the synchronized block. But in the first case, the first if might be reading a stale value (i.e. the thread might wait() even though the flag is already true). So you still need volatile.
If you're checking and modifying the flag from different threads, it nees to be at least declared volatile, for threads to see the changes.
Putting the checks in synchronized blocks would work too.
And yes, it is a very basic thing in concurrency, so you should make sure you read up on the memory model, happens-before and other related subjects.
First of all: the lock.wait(1000) will return after a second even if the other thread did not send notify.
Secondly: your friend is right, in this case you have shared data accessed by different threads so acces to it should better be guarded with a lock like in your code.
Thirdly: mark your flag variable as volatile so different threads make sure they are always using the last "written" value
And finally: I would also put the if (!flag) code in a synchronized block -> it is also accessing the flag variable...
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between volatile and synchronized in JAVA (j2me)
I am a bit confused with the 2 java keywords synchronized and volatile.
To what i understand, since java is a multi-threaded language, and by using the keyword synchronized will force it to be executed in 1 thread. Am i correct ?
And volatile also does the same thing ?
Both volatile and synchronized guarantee visibility, but synchronized also provides atomicity:
if one thread thread reads a volatile variable, it has the guarantee to see the previous writes to that same variable, including if they were done by other threads
synchronized blocks give the same guarantee (provided the write and the read are done holding the same monitor) but also provides atomicity guarantees: all instructions within a synchronized block will look atomic from another thread synchronized on the same lock.
For long and double read and write operation are not atomic.
volatile is a modifier you can put on a variable to make read and write operations atomic (including long and double)
The article Atomic Access got more information about it.
Basically it is for making sure that if one thread changed the value of the variable the rest of the threads will see that change and will not able to read it while its written.
Java multi-threading involves two problems, ensuring that multiple operations can be done consistently, without mixing actions by different threads, and making a change in a variable's value available to threads other than the on doing the change.
In reality, a variable does not naturally exist at a single location in the hardware. There may be copies in the internal state of different threads, or in different hardware caches. Simply assigning to a variable automatically changes its value from the point of view of the thread doing the assignment.
If the variable is marked "volatile" other threads will get the changed value.
"synchronized" also ensures changes become visible. Specifically, any change done in one thread before the end of a synchronized block will be visible to reads done by another thread in a subsequent block synchronized on the same object.
In addition, blocks that are synchronized on the same object are forced to run sequentially, not in parallel. That allows one to do things like adding one to a variable, knowing that its value will not change between reading the old value and writing the new one. It also allows consistent changes to multiple variables.
The best way I know to learn what is needed to write solid concurrent code in Java is to read Java Concurrency in Practice
Essentially, volatile is used to indicate that a variable's value will be modified by different threads.
Synchronized is a keyword whose overall purpose is to only allow one thread at a time into a particular section of code thus allowing us to protect, for example, variables or data from being corrupted by simultaneous modifications from different threads.
It is as complicated as described lengthy in Java Memory Model.
Synchronized means that only one thread can access the method or code block at a given time.
Volatile handles the communication between threads. Here is a nice explanation: http://jeremymanson.blogspot.be/2008/11/what-volatile-means-in-java.html
Volatile keyword will make every thread to read or write as an atomic operation in memory location. If you do not use volatile, that variable may be cached by threads, and threads may be reading/writing cached copy instead of actual copy.