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.
Related
I know how multithreading works, how to use synchronized methods/blocks - but there is one thing that I can't find on web and it's not clear for me.
Let's say that we have have:
public class Parent {
public Child child;
public Parent(){
child = new Child();
}
}
public class Child{
public int health;
public int mana;
public Child (){
health = 100;
mana = 100;
}
}
This is obvious, that if I want to access health from two different threads, I need to make a getter like this:
public synchronized int getHealth(){return health;}
It's the same variable, when we touch it from two thread at once - it may break.
But what with the whole 'child' object? Can I for example make operations on mana on thread 1 and on health on thread two? In this way, I don't touch the same variable, but I'm still using 'child' on two different threads - so it may be unsafe. Should I also synchronize while using 'child'?
Edit - an example;
gameloop.player_me.setX(5);
gameloop.player_me.setY(5);
I am changing X and Y from two threads - it's obvious that setX && setY are synchronized. But I'm also accesing other variables in gameloop from a third thread. Should I synchronize on gameloop?
A synchronized method implicitly locks on this, so no, two threads cannot simultaneously get health and mana because the same object is locked for both. You could, however, use different lock objects for both of them by using a synchronized statement:
class Child {
private int health, mana;
private Object healthLock, manaLock;
public int getHealth() {
synchronized(healthLock) {
return health;
}
}
public int getMana() {
synchronized(manaLock) {
return mana;
}
}
}
This is obvious, that if I want to access health from two different threads, I need to make a getter like this:
No, it's not obvious. If you're concerned about thread-safety, then your fields shouldn't be public. In fact, they shouldn't be public, even if you're not concerned about thread-safety. And if they are private, then your Child class, as is, is effectively immutable since no method can modify any of the fields, so synchronization is not needed.
In this way, I don't touch the same variable, but I'm still using 'child' on two different threads - so it may be unsafe. Should I also synchronize while using 'child'?
It depends. Are the two variables related to each other? Or should they always be kept in a consistent state? Does your method modify the state?
Assuming the Child class is mutable, if both fields are completely unrelated, you don't need to use the same lock when modifying each of them. If they are related and should be kept in a consistent state, then you need to use the same lock to access them.
Every detail matters. It's impossible to give a definitive answer on what should be done if all we know is that a class has two fields.
Taking your last example, for example, you should probably not have a setX() and setY() methods in the first place. You should rather have a setCoordinates(Coordinates c) method and a Coordinates getCoordinates() method, which would be synchronized. This guarantees that x and y are modified together, atomically, and that no thread will ever see the new X without seeing the new Y yet. and thus think the player is in a location where it should never have been. Encapsulation is key.
In order to atomically update two and more volatile variables does it need to be guarded by lock with synchronized, reentrantReadWriteLock etc?
i.e.
volatile int vVar1, vVar1; // or AtomicInteger
/*** Needs to be updated atomically ***/
void atomicUpdate(int var1, int var2){
vVar1 = var1;
vVar2 = var2;
}
The same code is for java.util.concurrent.atomic variables.
If you need to assign two values atomically, chaning volatile int to AtomicInteger will not solve your race condition problem.
To solve your issue, you basically have two options:
Make the methods updating the variables synchronized (and maybe the methods reading those variables too)
Create an wrapper for your two variables, and make use of the fact that assignment is an atomic operation
Example for option 2:
volatile Vars vars;
void atomicUpdate(int var1, int var2) {
vars = new Vars(var1, var2);
}
public static Vars {
private int vVar1; // volatile if they need to be modified
private int vVar2;
}
I largely prefer option 2 since it is non blocking and allows you to cache any type of data.
Create a Class which encapsulates all of your state variables, then use AtomicReference to refer to them. This alleviates race conditions where a thread needs to set/check multiple values safely.
// set initial state
AtomicReference<MyState> ref = new AtomicReference<MyState>();
ref.set(new MyState("abc", "def"));
// .. Thread 1 needs to change the state:
ref.set(new MyState("xyz", "def"));
// .. Thread 2 needs to read the state (consistently):
MyState state = ref.get();
if ("test1".equals(state.a)) { }
else if ("test2".equals(state.b) { }
The benefit here is that Thread 2 is able to read MyState.a and MyState.b consistently from the same MyState instance, as opposed to having the MyState instance variable it's referencing change in-between checks.
I want to update my two variables atomically
You can't. There are no atomic operations in the Java language or in the Java standard library that span more than one variable.
You can probably solve your problem using the synchronized keyword, but using synchronized is different from using atomics because, in order for it to work, the threads must cooperate with one another.
If there is a specific relationship that must always exist between those two variables (a.k.a., an invariant), and if you can't update the variables without temporarily breaking the invariant, then you must synchronize the code that does the update, and you must also synchronize every other block of code that expects the invariant to be true.
That's because, when you write this:
synchronized(foo) { ... }
It doesn't prevent other threads from doing anything except synchronizing on the same object at the same time.
Also note: Once you have properly synchronized all access to the variables, then you won't need them to be volatile. That's because whatever one thread writes to memory before releasing a lock is guaranteed to become visible to any other thread that subsequently acquires the same lock.
An alternative would be to use a volatile array:
private volatile int[] var;
void update (int var1, int var2) {
var = new int[] { var1, var2 };
}
that would be atomic but it assumes that the rest of your code does not access vVar1 and vVar2 directly. There may be better options depending on what you are trying to achieve - for example you could create an ad hoc thread safe holder class (typically immutable) for the two ints.
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.
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
Is it safe/acceptable practice to lock on a private field variable (instead of using a lock object)? This way, I could have different locks for different purposes. Example below:
class Test {
private Integer x = 0;
private Integer y = 0;
public void incrementX() {
synchronized(x) {
x++;
}
}
public void decrementX() {
synchronized(x) {
x++;
}
}
public void incrementY() {
synchronized(y) {
y++;
}
}
public void decrementY() {
synchronized(y) {
y++;
}
}
Or should I have a lock object for each private member I wish to lock? Example:
class Test {
private final Object xLock = new Object();
private final Object yLock = new Object();
private Integer x = 0;
private Integer y = 0;
...
}
Or should I just have a single general lock and use that for all private variables that require locking? Example:
class Test {
private final Object objLock = new Object();
private Integer x = 0;
private Integer y = 0;
...
}
Beware to always use a final member var for the lock! If you use an Integer, for example, and you plan to change it, that will be very bad practice since each call will see a different object and cause a data race.
Whether you use one or several locks depends on the coordination scheme you want to achieve, so it's entirely domain-specific. You must think through carefully which operations are and which aren't mutually exclusive and assign locks to them appropriately. There is no single best practice here.
If you have two orthogonal operations on your object that may happen simultaneously without causing any datarace, that's a case for two locks. In your example there are two Integers, each changing independently. I see this as a case for two locks. If you had more complex code where in at least one operation you needed to access both Integers, that would tie them together and then you would need a single lock.
It's perfectly acceptable to lock on a private field, as long as this field is an object. Primitives don't have an intrinsic lock, and the first snippet is thus invalid.
I would however avoid locking on a private field if this field is accessible from the outside (using a getter, for example), as this would allow anyone to lock on the same object for different purposes. The second solution is thus the cleanest, IMHO.
Using a single lock is counter-productive, since it prevents concurrent access to methods which should be able to run concurrently. It's thus generally better to have fine-grained the locks.
EDIT:
now that you have changed your question and use wrapper objects, the locking on the private Integer instances is really not a good solution, as you change the values of these variables inside the methods. Use final fields as locks.
Remember that x++, if x is an Integer instance, is equivalent to:
int temp = x.intValue();
temp++;
x = Integer.valueOf(temp);
Moreover, since Integer.valueOf() caches Integer instances, you might have several classes using the same Integer instance to lock completely different things. A recipe for slow execution and deadlocks.
I think you should have two different lock for the two fields. You lock the object to prevent two or more thread access the same object at the same time.
You can also take a look to the Lock object in java http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
It is more performant than the synchronize, and in the java.util.concurrent there are some utility class to work with locks (also a ReadWriteLock, if you need it)
AFAIK the lock object you use is only as an ID. I mean, you can use whatever object you want. The only important thing is "if two things must be mutually exclusive, then they must use the same lock".
So the approach of using the very own var seems ok.
BUT, remember!!
I don't think you can lock on a primitive, it must be an Object
If you change the field value, next process will acquire a different lock!!!
So the separate lock seems safer. Except you are absolutely sure your field is not going to change (in fact, you should declare it as final).