I have a class with a global variable, Integer clock, initialized to 0. It passes 'clock' to a few thread constructors, starting the threads also. It seems increments to 'clock' can be seen within the thread, but in their calling process, 'clock' is always 0. Because Integer is an object and objects are passed by reference, I would expect changes to 'clock' to be seen everywhere. Is this not the case?
Use an AtomicInteger instead of an Integer.
An int value that may be updated atomically. See the java.util.concurrent.atomic package specification for description of the properties of atomic variables. An AtomicInteger is used in applications such as atomically incremented counters, and cannot be used as a replacement for an Integer. However, this class does extend Number to allow uniform access by tools and utilities that deal with numerically-based classes.
Integer is an immutable object so you cannot change its value from another thread. And since it must be declared final when you use it in the thread you cannot reassign the variable.
A way around this is to create a wrapper for Integer that is mutable
class MutableInteger {
private int integer;
synchronized void setInteger(int integer) { ... }
synchronized int getInteger() { ... }
}
Related
this class can be used in multi thread because it is thread-safe.
public class Hello {
private int value = 0;
public synchronized int get() {
return value;
}
public synchronized void set(int value) {
this.value = value;
}
}
i know that the reason that we must use synchronized when get() ,besides set() is memory visibility.
and java volatile keyword can be used for memory visibility.
so then.. this class is also thread-safe??
public class Hello {
private volatile int value = 0;
public int get() {
return value;
}
public synchronized void set(int value) {
this.value = value;
}
}
In your specific example, you don't need that extra synchronized. Given that you have already mentioned memory visibility (aka happens-before), I won't go deeper to explain this.
However, it does not apply generally. There are several assumptions in your example making it enough to simply use volatile
Type of value
Although you are simply doing a simple retrieval/assignment of value, it is not always guaranteed to be atomic for all data type. Iirc, Java only guarantee that such operation is atomic for int and types smaller that int. Which means, for example, if value is of type long, even you have declared it with volatile, you may still corrupt value with your above example
Operations on value
Ok, let's assume it is an int. In your example, you are simply getting and assigning an int for which the operation is atomic, hence simply using volatile is enough. However if you have another method doing something like value++, using volatile is not sufficient. In such case, you may either consider using Atomic* or use synchronized
Update: I later found that JLS https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7 mentioned that using volatile would enforce atomic read/write on double/long. So my original point 1 was actually wrong
In your example, there's no need to use synchronized in neither the get() nor the set method, given the value attribute is declared with the volatile keyword.
This is because the volatile keyword forces a happens-before relation between writer and reader threads.
Java Language Specification, Section 8.3.1.4. volatile fields:
The Java programming language allows threads to access shared variables (§17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.
The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.
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).
So, in your case, there's no need to synchronize the get() and set() methods.
In your class Hello there is only one field int value. Synchronized locks whole object and thus heavy operation, Instead you can use AtomicInteger. Since Atomic* variables are faster. Volatile just satisfies "happens before" you cannot achieve atomicity for operations like "check then act" with volatiles.
To make Hello class thread-safe, the best way
import java.util.concurrent.atomic.AtomicInteger;
public class Hello {
private AtomicInteger value;
public int get() {
return this.value.get();
}
public synchronized void set(int value) {
this.value.set(value);
}
}
As mentioned in this post
If some object has only one field or its critical updates are
limited to only one field of object so instead of using
synchronization or other thread safe collections , Atomic variables
(AtlomicInteger, AtomicReference etc.) can be utilized.
For the following simplified class:
public class MutableInteger {
private int value;
public MutableInteger(int initial) {
synchronized(this) { // is this necessary for memory visibility?
this.value = initial;
}
}
public synchronized int get() {
return this.value;
}
public synchronized void increment() {
this.value++;
}
...
}
I guess the general question is for mutable variables guarded by synchronization is it necessary to synchronize when setting the initial value in the constructor?
You're right, without the synchronized block in the constructor there is no visibility guarantee for non-final fields, as can be seen in this example.
However in practice I would rather use volatile fields or the Atomic* classes in situations like this.
Update: It is also important to mention here that in order for your program to be correctly synchronized (as defined by the JLS), you will need to publish the reference to your object in a safe manner. The cited example doesn't do that, hence why you may see the wrong value in non-final fields. But if you publish the object reference correctly (i.e. by assigning it to a final field of another object, or by creating it before calling Thread.start()), it is guaranteed that your object will be seen at least as up-to-date as the time of publishing, therefore making the synchronized block in the constructor unnecessary.
Though you've accepted an answer, let me add my two cents.
Based on what I've read, synchronization or making the field volatile would not grantee the following visibility.
A thread T1 may see a not-null value for this, but unless you've made the field value final, there's a good chance of thread T1 seeing the default value of value.
The value could be a volatile or been accessed within synchronized blocks (monitor acquire and release), either way provided that the correct execution order was followed, there's happens-before edge from the write to the read of value. There's no argument on that.
But it's not the happens before edge that we have to consider here, but the correct publication of the object itself(MutableInteger).
Creating an object is twofold where the JVM first allocates a heap space and then start initializing fields. A thread may see a not-null reference of an object but an uninitialized field of that as long as the said field is not final (Assuming reference has been correctly published).
For the following class, what are the implications of making mNumSides final? Is "thread-safety" affected?
class Shape {
private int mNumSides;
public Shape(int numSides) {
mNumSides = numSides;
}
public int getNumSides() {
return mNumSides;
}
}
Absolutely. final keyword guarantees that all the threads see the same value of mNumSides at all the times. More information on final and its impact on the Memory Model here.
Without using final the object might be inconsistently published to other threads, and there is probability (extremely low though) that a thread might see the value of mNumSides as 0 rather than numSides as passed in constructor.
Making it volatile or static will also work though.
Num sides cannot be reassigned if it is declared as final. There'd be no risk of multiple threads reading different values due to it not being declared as volatile.
So, declaring the variable as final makes the class thread safe. As of now its not thread safe.
Declaring an object final keeps its reference from being reassigned, however if the object had internal data, that data could be reassigned which would not be thread-safe. This is an important point made by Colin on another answer.
In this case the data is a primitive, and so has no internal data. So here, declaring it final works fine.
I've following class
class A{
private int id =0;
public void setMessageId(Message m) {
synchronized(m) {
m.setId(id++);
}
}
}
Can two threads with same instance of class A with DIFFERENT instances of Message enter into the synchronized block at same time and set same id to different instances of message?
Yes. You need to synchronize on the object that holds the id field (in this case 'A') or some common object.
Yes. Since the block is synchronized on the message, two threads using two different message instances can enter the synchronized block concurrently, and both get the same ID.
Make the method synchronized, and everything will be fine. Or use an AtomicInteger.
If you only synchronize on m, then two objects will be able to modify the same instance of A. You need to synchronize on the object that stores the value id.
Sure, because you synchronize on different objects.
If all what you need for this purpose it's ID generation better to use java.util.concurrent AtomicInteger.
For example like this:
private AtomicInteger counter;
public int getNextUniqueIndex() {
return counter.getAndIncrement();
}
1. As the synchronized lock is on the instance of message, and then two thread with different message object can definately access this block at the same time.
2. Even if they are setting the same instance variable, its like a personal copy which is one per object.
3. Thread changing the variable id of one object will Not effect the id of other object.
Yes:
The lock object is obtained for the m object which are 2 different objects for each of your threads so yes they can. You will need to obtain a lock which is shared between those 2 and that A class in your case.
Yes, because they both have locks to different objects.
One option without self made synchronization at all is to use AtomicInteger:
class A{
private final AtomicInteger id = new AtomicInteger();
public void setMessageId(Message m) {
m.setId(id.incrementAndGet());
}
}
Method incrementAndGet incerements value by one and returns updated value.
If multiple threads read a primitive type that has been previously set and does not change ever after, can they get a wrong value?
For example, assume the following simple code excerpt:
public static final boolean proceed = read(); // Read the value from a file
public static void doSomething() // Method accessed by multiple threads
{
if (proceed)
{
System.out.println("TRUE");
}
else
{
System.out.println("FALSE");
}
}
Assuming that the proceed variable is initialized to true, is it possible that, in one or more of the multiple threads that simultaneously run the doSomething() method, the printed message is FALSE?
If the proceed variable was mutable, surely that would be possible, hence the need for synchronization, or for using an AtomicBoolean (e.g., as per this question). But in this case proceed is immutable and only set once, during the static initialization of the containing class.
Similarly for other primitive types, if a value is set as final, it should always be thread-safe to access it afterwards, correct?
The fact that your variable is final guarantees that all threads will see it in a consistent post-initialisation state. This is applicable to objects' references too (i.e. all threads will see a non null value of the Object if it has been initialised to a non null reference - but if your object is not thread-safe, some threads might see the object itself in an inconsistent or stale state).
ps: that is assuming your read method does not try to read the boolean value in which case it would see the default (false) value.
You are saying it is immutable (static and final), so we can safely say it is thread-safe.
The reference is thread-safe because it's immutable.
If it were mutable, you would need to use the volatile keyword to make sure you get the latest value if modified in another thread.
Do you ever use the volatile keyword in Java?
Since proceed is static and final , it can not be reassigned which turns in to thread-safe.
static says it is class level and final says it's value can't be changed and this is a primitive so defiantly this immutable and hence thread-safe .