I have recently begun to understand how the Java Memory Model works (I don't fully yet).
I now understand that if I have non-final, non-volatile fields in my classes then it is possible for the value of those fields to not be immediately visible to other threads post construction e.g.
public class Example {
Object a;
Object b;
public Example() {
this.a = new Object();
this.b = new Object();
}
}
Example e = new Example();
// now imagine we are in another thread
e.a // could this in theory be null?
e.b // could this in theory be null?
What I'm not sure about is weather if I add a third volatile variable and set it at the end will the writes to a and b be guaranteed to be visible to other threads?
public class Example2 {
Object a;
Object b;
volatile Object c;
public Example2() {
this.a = new Object();
this.b = new Object();
this.c = new Object();
}
}
// some where else
Example2 e2 = new Example2();
// are e2.a and e2.b guaranteed to be visible to all other threads? I know (e2.c will be)
This is not something I particularly want to use but I want to understand what would happen in this case.
The constructor runs in a single thread and the instance is not "visible" to other threads until the constructor completes.
So, in this example, a and b will only be seen in other threads as null if they are subsequently set to null post-constructor.
The volatile keyword addresses possible optimizations in which a thread may continue to use an old value for a field after it changes on another thread due to local caching of the value. By adding volatile to the field, such optimizations are disabled.
By the way, if there's a need to synchronize across threads, using volatile fields is not ideal. Using atomic classes or other constructs from java.util.concurrent is advisable.
Related
I have seen usage of synchronized block by this so far but recently I learned that using dummy object is preferable. I found the following topic related to this.
Java synchronized method lock on object, or method?
As a summary, in the code below, two different object can not run addA and addB concurrently as both uses this for lock.
private int a;
private int b;
public synchronized void addA(){
a++;
}
public synchronized void addB(){
b++;
}
I am confused if I use dummy object for lock, what will be different if I use the line below in both method to synchronize? Because still they would have same lock.
synchronized(dummyObject){
...
}
So what it means that I should have two different dummy object for each method to use with sycnhronized as?
public void addA(){
synchronized(dummyObj1){
a++;
}
}
public void addB(){
synchronized(dummyObj2){
b++;
}
}
That is exactly the point of lock objects - you can use different locks for different operations. Assuming it makes sense to run addA and addB concurrently (and from the looks of it - it definitely does), you should indeed have two separate locks, one for each method.
You are correct. In this case you need two different objects to synchronize on them separately.
For locking purpose the easiest way is to create Object objects.
Object lock1 = new Object();
Object lock2 = new Object();
I have two classes A and B:
class A {
private final String someData;
private B b;
public String getSomeData() { return someData; }
public B getB() {
if (b == null) {
b = new B(someData);
}
return b;
}
}
where B is immutable and computes its data only from an instance of A. A has immutable semantics, but it's internals are mutable (like hashCode in java.lang.String).
When I call getB() from two different threads, and the calls overlap, I assume each thread gets its own instance of B. But since the constructor of B gets only immutable data, the two instances of B should be equal.
Is that correct? If not, must I make getB() synchronized to make it thread-safe?
Assume that B implements equals(), which compares all instance variables of B. Same for hashCode()
This is not thread-safe, because you haven't created any "happens-before" relationships with volatile or synchronized, so it's possible for the two threads to interfere with each other.
The problem is that although b = new B(someData) means "allocate enough memory for an instance of B, then create the instance there, then point b to it", the system is allowed to implement it as "allocate enough memory for an instance of B, then point b to it, then create the instance" (since, in a single-threaded app, that's equivalent). So in your code, where two threads can create separate instances but return the same instance, there's a chance that one thread will return the other thread's instance before the instance is fully initialized.
For "But since the constructor of B gets only immutable data, the two instances of B should be equal."
As you understand its not thread safe, one thread might get un-initialized B instance (B as null or inconsistent state where somedata not yet set) others might get b instance with somedata set.
To fix this you need synchronized getB method or use synchronized block with double-check lock or some non-blocking technique like AtomicReference. For you reference I am adding here sample code for how to achieve the correct threadSafe getB() method using AtomicReference.
class A {
private final String someData = "somedata";
private AtomicReference<B> bRef;
public String getSomeData() { return someData; }
public B getB() {
if(bRef.get()== null){
synchronized (this){
if(bRef.get() == null)
bRef.compareAndSet(null,new B(someData));
}
}
return bRef.get();
}
}
class B{
public B(String someData) {
}
}
Consider below scenario, it says if str is volatile it means any update by any thread accessing str, will directly update on main stack instead of local Thread cache.
class A{
volatile String str;
volatile B b=new B();
}
class B{
int a;
C c;
}
For b volatile object, how scenario will work?
I read few links it says only reference is volatile and not the property of object itself, what does that mean, can some one help me with some example as I am finding it little bit difficult to understand.
if reference is synchronized, then how it will help, what is the use of it?
First scenario:
thread 1 does a.b = new B();
then thread 2 does B b = a.b;
In this case, you have the guarantee that the object referenced by b in the second thread is the new B() that the first thread has assigned to the variable.
Second scenario:
thread 1 does a.b.setFoo("hello");
then thread 2 does String s = a.b.getFoo();
In this case, you have no guarantee regarding the value of s in the second thread. It could be "hello", or it could be a previous value of a.b.foo (unless the foo attribute in class B is itself volatile, or the setters and getters are synchronized).
It is guranteed or not that every thread sees the value of an instance initializer (the expression right to the equal sign of a field) for a non-final field? For example:
class Foo {
private boolean initialized = false; // Initializer
private final Lock lock = new ReentrantLock();
public void initialize() {
lock.lock()
try {
// Is initialized always false for the first call of initialize()?
if (initialized) {
throw new IllegalStateException("already initialized");
}
// ...
initialized = true;
} finally {
lock.unlock();
}
}
}
In that specific case you are fine because false is also the default value for boolean fields. If your instance variable initialisation were:
private boolean initialized = true;
Then you would have no guarantee that a thread would read true.
Note that if the field were static, you would have such a guarantee due to class loading semantics.
Reference: JLS 17.4.4 (emphasis mine)
The write of the default value (zero, false, or null) to each variable synchronizes-with the first action in every thread.
Although it may seem a little strange to write a default value to a variable before the object containing the variable is allocated, conceptually every object is created at the start of the program with its default initialized values.
The same stands for initialzers that is true for referencing fields:
If you want other threads to see its current value you have to use volatile.
volatile is not surefire however: most of the case you have to use synchronized or other means of synchronizing in order to be sure but in this case a volatile will be enough.
Please refer to this question about the usage of volatile and about thread safety.
Another thing is that only one thread can construct an object and the instance initialization is happening when the object is being constructed. You have to taker care however not to let the this reference escape from the constructor.
It seems to me that what you are looking for is a thread-safe way of lazy initialization. Since direct use of low-level classes such as ReentrantLock can be quite hard to do correctly, I would instead recommend the double-check idiom:
private volatile FieldType field = null; // volatile!
public FieldType getField() {
FieldType result = field; // read volatile field only once, after init
if (result == null) {
synchronized(this) {
result = field;
if (result == null) {
result = computeFieldValue();
field = result;
}
}
}
return result;
}
Note that Double-Check locking requires at least Java 1.5. On older versions of Java it was broken.
A non-final field alone is not guaranteed to be correctly seen, unless you have some other protection such as a lock or synchronized block. i.e. in this case it will always be correct due to the way the value is used.
BTW: For simplicity reasons, I suggest you always structure your code so the component is initialized in the constructor. This avoids such issues as checking the objects is not initialised or initialised twice.
I am unsure if the volatile keyword should also be used for non-primitives. I have a class member which is set/assigned by one thread, and accessed by another thread. Should I declare this member volatile?
private /* volatile */ Object o;
public void setMember(Object o) {
this.o = o;
}
public Object getMember() {
return o;
}
Here, setMember(...) is called by one thread and getMember() is called by another one.
If it was a boolean, for example, the answer would be yes.
I am using Java 1.4 and the member in this case is read-only. So I am only caring about visibility in this case, hence my question about the volatile keyword.
Yes - volatile has exactly the same significance for reference-type fields that it has for primitive-type fields. Except that in the case of reference types, the members of the object the field refers to must also be designed for multi-threaded access.
You can, and it may be helpful, but remember the keyword just applies to the setting of the reference. It has no effect on multi-thread visibility of the properties inside that object. If it is stateful, you probably want to synchronize around each access to it anyway, to ensure the desired happens-before relationships.
Yes, your code is correct. In this case the reference itself is volatile, so chances to the reference are automatically visible in all other threads, but not changes to the object being referenced.
If we look up AtomicInteger class, it has declared value as volatile , So it can be used in multi-threaded environment without any thread cache issue.
public class AtomicInteger {
private volatile int value;
/**
* Gets the current value.
*
* #return the current value
*/
public final int get() {
return value;
}
/**
* Sets to the given value.
*
* #param newValue the new value
*/
public final void set(int newValue) {
value = newValue;
}
}
But if you think reference to AtomicInteger it shelf will be modified with different AtomicInteger objects by many threads; then you need volatile for that reference too.
private volatile AtomicInteger reference = new AtomicInteger(0);
Mostly it won't be the case; only value of the object will changed; hence declare it as final.
private final AtomicInteger reference = new AtomicInteger(0);