Lets say you have:
public class Foo {
public Bar b;
}
public class Bar {
public int x;
public int y;
}
And then you call:
Foo f = new Foo();
....
synchronized(f) {
f.b.x = 3;
f.b.y = 5; //x and y must be adjacent primes at all times.
}
If our thread-safeness deep? i.e. does synchronized(f) prevent another thread (inside it's own synchronized(f) block) from seeing f.b while f.b is updated? What about using synchronized(this) instead?
Asking whether synchronization is "deep" shows that you don't yet fully understand how Java thread "synchronization" works. All beginning Java programmers usually have the same misconception -- "synchronizing on f makes access to f's fields thread-safe". This is not true.
When one thread is executing your synchronized(f) block, no other thread can enter any block or method synchronized on the same object. THAT IS ALL.
There is no reason why you must protect the mutable fields of f by synchronizing on f. You can synchronize on any Object at all you want, as long as you always use the same one, and as long as you always synchronize when you are accessing/modifying the fields of f.
Conversely, synchronizing on f does NOT mean that your access of f's fields is necessarily thread-safe. You could have some other code elsewhere in the program, modifying f's fields without any synchronization at all, or synchronizing on a different Object.
If this seems confusing, that's because it is. The designers of Java made a bad choice (to associate an implicit mutex with each and every object), and we just have to deal with it.
Not at all.
The synchronized keyword only affects other synchronized blocks around the same object.
It has nothing to do with the object itself.
Related
I am recently reading the book "Java Concurrency in Practice". One example of "safe publish" it gives is to initialize a private int field n during construction, and a later assertion on that field n == "expect value" through a public method could still be failed if it is called from another thread. This makes me feel worried in that, assuming all private fields are initialized only once, do we still have to mark them as volatile or wrap them into ThreadLocal or even use an AtomicReference to get a pure thread safe java class, since these private fields, though not visible outside, definitely could be referenced by the method(s) called by other threads.
EDIT: Just to be clear - the assertion is failed because the calling thread sees a stale value of n, even though it has been set during construction. This is a clearly a memory-visibility issue. Problem is whether synchronizing on n is worthy of the overhead after all, since it is only initialized once, and as a private field, author can make sure it won't be changed again.
This specific case is properly documented in the JSR 133: Java Memory Model and Thread
Specification. It even has a dedicated code sample page 14 section 3.5 Final Fields that exactly match your question.
To summarize:
A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object’s final fields.
There is no guarantee for non final fields
It means that you have to make sure that an happens-before occurs between your object creation in a thread and its usage in another thread. You can use synchronized, volatile or any other mean to enforce an happens-before.
Since you say in another comment that the field is only set during construction, I would make it... final. Also, such shared objects between threads could suggest some design smell; I would review my design to make sure that I am not creating an overly complex, tightly coupled, hard to debug system.
If the fields are never used outside the class, wrapping their usages with synchronized blocks or inside synchronized functions, two threads won't concurrently modify these fields.
volatile keyword is just a part of thread safety. It only makes the value of a field never be cached, always read from memory. Take this example.
private int myPrivateField = 0;
void someFunction() {
while(myPrivateField ==0) {
}
}
void otherFunction() {
myPrivateField = 1;
}
If someFunction() is called from one thread and it's running for a while,
when you call otherFunction() the value of myPrivateField will not be
"updated" inside someFunction, it was cached to 0 as an otimization.
Making myPrivateField as volatile, the value will always be the one
in memory.
For the example, there won't be much difference for the functions be
synchronized, but without synchronization, you can read a value in an
inconsistent state.
Only final fields are guaranteed to be visible after constructor. Any other field requires some visibility mechanism, such as synchronized or volatile.
This is not as much of a burden as it seems: if the field is not final, then it can be changed by another thread while you're reading it. If teh field can be changed, then the last assigned value must be propagated from the writer thread to the reader thread, whether the writer thread called the constructor or a setter.
If the change in this field is not related to any other field in the class, then the field should be volatile. If the field is related to other fields in the class, then use synchronized or other, more modern locking primitives.
Not answering the entire question, but it should be pointed out that using ThreadLocal is exactly the wrong thing to use if you want to ensure visibility of updated values in all threads. Consider the following code:
class Test {
private static final ThreadLocal<Integer> value = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
System.out.println("From main Thread, value is " + value.get());
value.set(42);
System.out.println("Value has been changed");
Thread t = new Thread() {
public void run() {
System.out.println("From other Thread, value is " + value.get());
}
};
t.start();
t.join();
System.out.println("From main Thread, value is " + value.get());
}
}
This will output the following:
From main Thread, value is null
Value has been changed
From other Thread, value is null
From main Thread, value is 42
i.e. the other thread doesn't see the updated value. This is because changes to the value of a ThreadLocal is, by definition, localized to the thread which changes it.
My personal preference would be to use AtomicReference, since this avoids the risk of forgetting to synchronize externally; it also allows things like atomic compare-and-set, which you don't get with a volatile variable. However, this may not be a requirement for your particular application.
Let's say I have a JavaBean User that's updated from another thread like this:
public class A {
private final User user;
public A(User user) {
this.user = user;
}
public void aMethod() {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
...a long running task..
user.setSomething(something);
}
});
t.start();
t.join();
}
public void anotherMethod() {
GUIHandler.showOnGuiSomehow(user);
}
}
Is this code thread safe? I mean, when the thread that created A instance and called A.aMethod reads user fields, does it see user in the fresh state? How to do it in appropriate thread safe manner?
Note that I can't modify the user class and I don't know if it's thread safe itself.
Is this code thread safe? ... does it see user in the fresh state?
Not especially - the fact that user is final in your code makes almost no difference to thread safety other than the fact that it cannot be replaced.
The bit that should change is the instance variable that is set by setSomething. It should be marked as volatile.
class User {
// Marked `volatile` to ensure all writes are visible to other threads.
volatile String something;
public void setSomething(String something) {
this.something = something;
}
}
If however (as you suggest) you do not have access to the User class, you must then perform a synchronization that creates a memory barrier. In its simplest form you could surround your access to the user with a synchronized access.
synchronized (user) {
user.setSomething(something);
}
Added :- It turns out (see here) that this can actually be done like this:
volatile int barrier = 0;
...
user.setSomething(something);
// Forces **all** cached variable to be flushed.
barrier += 1;
marking field as final just means that reference cannot be changed. It means nothing about thread safity of class User. If methods of this class that access fields are synchronized (or use other synchronization technique) it is thread safe. Otherwise it is not.
final only makes the reference not re-assignable, but if the reference points to a mutable class, you can still alter the state inside that object, which causes thead-unsafe.
Your code is only thread safe if the User class is immutable, I.e. all properties of User cannot be altered outside the object, all references in the class point to other immutable class.
If it is not case, then you have to properly synchronize its methods to make it thread safe.
Note that I can't modify the user class and I don't know if it's thread safe itself.
You have to synchronize your access when accessing the User object.
You can for example use the User object to synchronize, so just wrap every access on the user object with something like:
synchronized(user) {
// access some method of the user object
}
That assumes that the user object is only accessed in your threads asynchronously. Also keep the synchronized blocks short.
You could also build a threadsafe wrapper around the user object. I would suggest that if you have a lot of different calls, the code gets cleaner and better to read that way.
good luck!
Concerning threading, finalfields are just guaranteed to be consistent in case of constructor escape, since the JSR-133 about Memory Barrier mechanism:
The values for an object's final fields are set in its constructor.
Assuming the object is constructed "correctly", once an object is
constructed, the values assigned to the final fields in the
constructor will be visible to all other threads without
synchronization. In addition, the visible values for any other object
or array referenced by those final fields will be at least as
up-to-date as the final fields. What does it mean for an object to be
properly constructed? It simply means that no reference to the object
being constructed is allowed to "escape" during construction. (See
Safe Construction Techniques for examples.) In other words, do not
place a reference to the object being constructed anywhere where
another thread might be able to see it; do not assign it to a static
field, do not register it as a listener with any other object, and so
on. These tasks should be done after the constructor completes, not in
the constructor.
However, nothing ensures automatic thread-safety about any final fields in the remaining object's life (meaning after wrapping class's constructor execution).. Indeed, immutability in Java is a pure misnomer:
Now, in common parlance, immutability means "does not change".
Immutability doesn't mean "does not change" in Java. It means "is
transitively reachable from a final field, has not changed since the
final field was set, and a reference to the object containing the
final field did not escape the constructor".
Yes, this is safe. See
Java Language Specification (Java 8) Chapter 17.4.4:
The final action in a thread T1 synchronizes-with any action in another thread T2 that detects that T1 has terminated.
T2 may accomplish this by calling T1.isAlive() or T1.join().
Put this together with 17.4.5. Happens-before Order:
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. [..] If an action x synchronizes-with a following action y, then we also have hb(x, y).
So after you call t.join(); in your code you will see the updated changes. Since "the thread that created A instance and called A.aMethod" can impossibly read the value after calling aMethod and before t.join is called (because it is busy with method aMethod), this is safe.
Assuming this class:
public class AmIThreadSafe {
private int a;
private int b;
AmIThreadSafe(int a, int b) {
this.a = a;
this.b = b;
}
}
Assuming that instance's reference to this class (declared as volatile) is accessible by some threads (leading to race condition) as soon as the this(reference) escapes:
volatile AmIThreadSafe instance = new AmIThreadSafe(1,2);
Here, I'm sure that the fact of assigning instance reference happens-before reading by threads.
But what about the AmIThreadSafe's fields?
Does the external volatile keyword also imply an happens-before relation concerning a and b fields?
Or is it rather possible to end up with any thread seeing stale values (default values 0 in this case since int) due to a potential statements reordering during constructor?
In other word, should I declare a and b final or volatile to prevent any surprises with the JMM or is just indicating volatile on the instance's reference enough?
----------------UPDATED POST - A GOOD ANSWER:----------------------------
The following article confirms by its sample that in my case, a and b are protected from JMM optimisations that prevent a permanent happens-before relation.
http://jeremymanson.blogspot.fr/2008/11/what-volatile-means-in-java.html
Declaring instance as volatile does not make its fields volatile, but if I understand your question correctly, then — yes, it's enough in your case.
Per §17.4.5 of the spec:
a volatile write in one thread happens-before any subsequent volatile read in another thread.
statements within the same thread have the happens-before relationship that you'd expect.
happens-before relationships are transitive.
So, if a thread perceives instance as having been initialized, then the initialization of instance happened-before it, and the initialization of instance's fields happened-before that, so the thread will perceive instance's fields as having been initialized.
No it's not enough to make it volatile. Thread safety depends on the usage though. E.g., this could still produce unexpected results if another thread is modifying the values.
assuming public variables for simplicity
volatile AmIThreadSafe instance = new AmIThreadSafe(1,2);
if (instance.x == 0) {
// instance.x might have changed between checking and assigning
instance.x = instance.x + 1;
}
volatile only applies to a variable (e.g., x and y are not automatically volatile just because instance is). This should be clear from JLS 8.3.1.4
The volatile in your case applies only to the reference of AmlThreadSafe. You still have to make the instance variables (a and b) volatile or access them in a synchronized block. Otherwise you can get stale data.
Yes.
thread 1 thread 2
1 write(a)
2 write(instance)
3 read(instance)
4 read(a)
Since instance is volatile, [2] happens-before [3].
Since happens-before is transitive, we have hb(1,2), hb(2,3), hb(3,4), therefore hb(1,4)
If a and b are only modified in the constructor, then in this case you should be fine because the object is created (and a and b set) BEFORE the reference is assigned to instance, and any other threads won't have locally-cached copies of the memory at those locations because it's a new object that the thread couldn't have seen before. In other words, I don't believe it's possible that another thread will ever be able to see the "default" value of 0 for a and b because the constructor will run completely before the object's reference is assigned to instance.
However if a and b can be modified after the constructor, then the other answers here are correct - you need synchronization around them.
If you are going to assume that a and b won't be modified outside of the constructor, then there's no reason not to make them final anyway, just to be safe.
Example :
class Something{
private volatile static Something instance = null;
private int x;
private int y;
private Something(){
this.x = 1;
this.y = 2;
}
public static Something getInstance() {
if (instance == null) {
synchronized (Something.class) {
if (instance == null)
instance = new Something();
}
}
}
return instance;
}
}
Explanation :
Lets say we have the above Code:
Now lets assume instance is not volatile for some time:
Thread#1 :
Comes in invoke getInstance method, Check for instance value{since null}, will go inside the IF condition, Access the Lock now again finds that instance == null, calls Something constructor. Now goes inside Constructor body.
As soon as Thread#1 goes inside Constructor body, Context Switch happens and now Thread #2 gets the turn to execute.
Thread#2 :
Invokes get Instance, But suddenly finds that instance is not null?Why{Reason will discuss just after this}and hence assign partially constructed Object to reference and returns it.
Now Situation is like this : Thread#1 Still needs to construct the Object Completely{needs to completely construct it} and Thread#2 got reference for partially constructed Object, and if it uses it like say reference.x //will print "x" Default Value and not "1"
Why partially constructed Object reference is returned in case Of Thread#2 ?
Reason is simple: Statements Reordering.
The Steps are simple for Object creation and reference association :
Allocate Memory in Heap.
Execute the Body of Constructor which will initialize class members.
Once above Step is completed, Reference to newly created Object.
But Sometimes Compiler can execute these Instructions out Of order, which means :
It might happen something like this :
Allocate Memory in Heap.
Reference to newly created Object.
Execute the Body of Constructor which will initialize class members.
Once the above two Steps happens and if Context Switching Happens, then reference will point to Object which is not initialized or it might be the case that Inside Constructor Body Context Switch happens then in that case reference will refer to partially initialized Object.
If such scenario occurs then reference will neither be null nor complete and hence it will break our Singleton motivation.
Now How Volatile will save our Life from such embarrassments :
As we know Volatile work with two principles : 1)Visibility 2)Happens Before Relationship.
Now Happens Before Relationship comes into Picture here.
So reference is volatile Write, so all statements should happen before any Volatile write.Again If we look at our Object construction steps:
Allocate memory for Object
Initialize member variables{Constructor Body}
Assign Object reference to volatile variable instance.
Step 3 has Volatile Variable write and as per Happens before .. All statements write guaranteed to be made available to step 3. And since it is volatile therefore No reordering will happen between volatile and non volatile statements, which was not the case in Old Java Memory Model.
So before executing Step 3, Step 1 and Step 2 are guaranteed to be happened and made available to Step 3. {In which order Step 1 and step 2 occurs we don't bother about it.}
So from this Thread will see either Completely created Object or null
As I am trying to get to grips with thread safety, I would like to know if this class is threadsafe? If two threads try to access its variables at any time it seems to me that it is thread safe because:
final variable is threadsafe by virtue of being immutable.
getter and setter are synchronized, so mObject can only be gotten, or set by one thread at a time. So there is no chance of two threads reading different values.
The method changeObj() is not synchronized but any block in it which deals with class variables (i.e. mObject) is synchronized.
Please tell me if I am wrong or if this class is not threadsafe.
public class MyClass{
private final String = "mystring"; //thread safe because final
private AnObject mObject;
public MyClass(){
//initialize
}
//only one class can set the object at a time.
public synchronized void setObj(AnObject a){
mObject = a;
}
//two threads trying to get the same object will not read different values.
public synchronized AnObject getObj(){
return mObject;
}
//better to synchronize the smallest possible block than the whole method, for performance.
public void changeObj(){
//just using local variables (on stack) so no need to worry about thread safety
int i = 1;
//i and j are just to simulate some local variable manipulations.
int j =3;
j+=i;
synchronized(this){
//change values is NOT synchronized. Does this matter? I don't think so.
mObject.changeValues();
}
}
}
No, it's not thread safe. You make sure only one thread can change the values in your AnObject at a time if it uses the changeObj() method, but you also provide a getter for this object, so any other thread could call changeValues() concurrently.
Your class in itself is thread safe in its current state (assuming any methods not shown here are), however you have one likely "bug" in your thinking;
mObject isn't 100% encapsulated, it is passed in through a setter and can be fetched through a getter. That means that any thread could get a reference to and call methods on the object referenced by mObject simultaneously without MyClass knowing about it.
In other words, AnObject's methods may need to be thread safe too.
At the very least, the synchronizing in MyClass doesn't in any way make mObject safe from threading problems.
Adding to Mr. JB Nizet's points, if AnObject.changeValues is a method that is designed to be overridden by clients, or calls such methods, then this, in the general case, opens the door for various unwanted behaviours, like deadlocks and data corruption. You must never cede control to alien code within a synchronized block. By "alien" I mean code not under your control. More details can be found in Effective Java, 2nd Ed, Item 67.
A final variable is not necessarily thread safe, only immutable final variables are thread safe -- that covers primitives and classes like String, or final variables of classes which themselves are thread-safe.
Your class is not thread safe because it exposes the variable a, but also requires it for its internal working.
The below example will demonstrate an example of how a could get into an inconsistent state.
Thread A
MyClass myClass = ...
myClass.changeObj();
// imagine Thread A is suspended during the synchronized block inside of
// changeObj()
Thead B
MyClass myClass = ...
AnObj anObj = myClass.getObj();
anObj.changeValues();
// uh-oh, I am modifying the state of this instance of anObj which is also
// currently being modified by Thread A
For MyClass to be truly thread safe you must do one of the following.
AnObj must also guarantee thread safety (by making methods that modify its state thread-safe)
AnObj must be immutable. That is, if you need to modify the state of AnObj you must create new instance of AnObj to hold the new state.
The getter for AnObj must not directly expose MyClass's instance of AnObj, but a rather return a copy of that instance.
Let's say I have a method, that is accessed by two or more threads and I want to make it thread safe.
public int getVal(int x, int y, MyClass myObj)
{
int z;
z = getInt(myObj);
return x + y + z;
}
In this, I think we don't have to synchronize for x + y as they are primitives.
Let's assume that getInt(myObj) modifies the state of myObj and that influences the value of z.
Therefore, I will have to provide synchronization for the line z = getInt(myObj); but only when both threads to pass same instance in 'myObj' reference. As the API's coder I would not know whether both threads would pass same instance for 'myObj' or not. In some case these threads might pass same MyClass instance in 'myObj' reference and in other cases they might pass different MyClass-instances in 'myObj' reference.
So, how would one ensure thread-safety for the line z = getInt(myObj)? (Surely, we do not want to synchronize when instances passed are different and only have to synchronize when instances passed are same. I it is clear that this cannot be determined).
Assuming that MyClass cannot be made immutable, I am thinking that the following could be a solution.
synchronized(myObj)
{
z = getInt(myObj);
}
Is it a correct solution? And, in what other ways can we ensure thread safety for
z = getInt(myObj); (but only in case of different instances)?
What you have is correct. When you synchronize on an object its locking on that instance not on that class. So if I pass the same *instance* of an object to two different methods, it will lock on that object correctly. However, if I pass two different instance, there won't be any locking because the two instance have each their own lock.
If getInt doesn't modify the state of this, then the method is thread-safe. The thread-safeness of the myObj object is the responsability of its class : MyClass, or of the object that holds it. Not the responsibility of all the methods which might take it as an argument, IMHO.
Your solution (synchronized(myObj)) is right, though : two threads won't be able to execute the getInt method concurrently if the same myObj is used in both threads. They will execute concurrently if the two myObjs are different.
synchronized(myObj) { z = getInt(myObj); }
will do what you intend, but synchronizing on a paremeter creates many other problems. For example, some other thread may already be syncrhonizing on that object (e.g., maybe that object has a synchronized method which is being called on it) and you could get into a deadlock case.
Synchronization should be encapsulated just like anything else. The best solution would be to add the getInt method to MyClass and synchronize on some private member within that method. This way nobody else can muck with what you are using to implement your sycnrhonization.
E.g.:
public class MyClass {
private Object lockObject = new Object();
public int getInt() {
synchronized(lockObject) {
// do your thing
}
}
}
See this: Avoid synchronized(this) in Java?
in reference to the importance of encapsulating your synchronization.
To answer "And, in what are the ways can we ensure thread safety for...but only in case of different instances", synchronize the entire method or create another, common object to act as a lock for all threads and synchronize on it instead of myObj.
If the only changes on myObject in question come from this getInt method, then your synchronization is enough. If there are other modificators out there, make sure they synchronize on the same object.
I disagree with all "your synchronized is correct" answers. What if you user has 2 threads, and one of them is holding a lock on the object already? Deadlocks ensues.
Also, x + y + z is not atomic. At CPU level, it'll become
int temp = x + y;
int res = temp + z;
I'll tell you more: long1 + long2 is not atomic on 32-bit machines.
I think your only option is to synchronize the entire method.