Following are just three "happens-before" rules of JMM. I am not listing the other rules as my question is related to these three rules only.
Questions
1st rule question - Let's say two threads A and B have synchronized blocks of code. Does the first rule mean that any variable set in a synchronized block in thread A, will be visible to the code in synchronized block of thread B, even if the variable is NOT declared as volatile?
2nd rule question - Let's say a thread A starts a thread B. Does the second rule mean that any variable set in a parent thread before calling start() will be visible to thread B even if the variable is NOT declared as volatile?
3rd rule question - Let's say a thread A interrupts a thread B. Does the third rule mean that any variable set in thread A before interrupting thread B will be visible to thread B after the interrupt is detected, even if the variable is not declared as volatile?
Finally, one more question:
Memory consistency effects: As with other concurrent collections, actions in a >thread prior to placing an object into a BlockingQueue happen-before actions >subsequent to the access or removal of that element from the BlockingQueue in >another thread.
Does this mean any variable set in a thread A before enqueuing an object in the blocking queue will be visible to thread B after dequeuing the object from the queue, even if the variable is NOT declared as volatile?
Basically through the above questions, I am trying to understand if the memory flush happens after these events such that the variables need not be declared as volatile in these cases.
1st rule question - Let's say two threads A and B have synchronized blocks of code.
Threads don't have code. Threads execute code.
Does the first rule mean that any variable set in a synchronized block in thread A, will be visible to the code in synchronized block of thread B, even if the variable is NOT declared as volatile?
Yes, Suppose we have:
private int i;
private final Object lock = new Object();
void foobar(...) {
...
synchronized(lock) {
i = ...;
}
}
int getI() {
synchronized(lock) {
return i;
}
}
If thread A calls foobar()
, and then thread B subsequently calls getI()
, then thread B will get the new value of i
.
But note! My example above does not include any way for you to prove which call actually happened first. If your program depends on those calls to happen in a particular order, then it's going to need more than just a mutex: It's going to need some means to make thread B wait()
for thread A to perform the update.
2nd rule question - Let's say a thread A starts a thread B. Does the second rule mean that any variable set in a parent thread before calling start() will be visible to thread B even if the variable is NOT declared as volatile?
Yes, that's what it means.
3rd rule question...
Yes again.
- ... BlockingQueue ...
Yes again.
...Through the above questions, I am trying to understand if the memory flush happens after these events such that...
Don't even think about "memory flush". That is not part of the Java language: If it happens, it's an implementation detail, and you don't need to worry about it unless you are implementing a JVM.
The only concept you need to worry about is the "happens before".
Whenever the JLS says that A happens before B, it means that if A happens in thread 1, and B happens in thread 2, and you can prove that A actually did happen before B in real-time, then any field that was updated by thread 1 before A happened will be guaranteed visible in thread 2 after B happens.