Accessing same variable from two different threads - java

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.

Related

Running an object with a synchronized method and normal method, concurrently?

Is it just that two synchronised methods that can't run concurrently?
For example, someone codes 2 Java classes.
public class A {
public synchronized void a1(){
//do something }
public void a2(){
//do something }
public synchronized int a3(){
int var = 0;
//do something changing var
return var; } }
public class B {
public void b1(){
//do something
}
public synchronized int b2(){
int var = 0;
//do something changing var
return var;
}
public void b3(){
//do something
}
}
With a main method,
public static void main(String[] args){
A firstA = new A();
A secondA = new A();
B firstB = newB();
//create some threads that perform operations on firstA, secondA and first B and start them
}
Assuming they run in parallel and call methods on the created objects and also assuming that none of these methods are prevented by other mechanisms from running currently.
Out of the methods in the example I gave, are there any that cannot be run concurrently if called at the same time by 2 different threads?
By running concurrently I mean, they will be sequenced so that one will finish before the other starts.
Assuming that there is no other synchronization involved, the only calls that will be mutually excluded are:
firstA.a1() vs firstA.a1()
firstA.a1() vs firstA.a3()
secondA.a1() vs secondA.a1()
secondA.a1() vs secondA.a3()
firstB.b2() vs firstB.b2()
This is because synchronized blocks have to use the same lock for them to have an effect on each other. When you mark a whole method as synchronized, the lock object will be the value of this. So methods in firstA will be completely independent of methods of secondA or firstB, because they use different locks.
The methods in your code that aren't marked synchronized won't even attempt to acquire any lock at all, they can run whenever they want.
Please note that mutual exclusion is just one aspect of multithreading. For your programme to work correctly, you also have to consider things like visibility and safe publication.
Of course, the answer depends on what "something" you "do" when you "do something", and since you don't show that, no one can answer. That's what happens when you omit the significant information. Don't omit the significant information.
What we can say is that the synchronized methods in A do not use the same lock as the synchronized methods in B.
If multiple threads access the same data, then they must synchronize with each other. The only way for threads to synchronize with each other is to use the same means of synchronization. If that's the use of synchronized, then they must synchronize on the same monitor (lock). So if the A methods and B methods access the same data from different threads, and who can tell if they do from what you show? then they won't work as shown.
If any of the unsynchronized methods access the same data from different threads, and the part you didn't show does not have other effective synchronization means, then they won't work.
All this depends on what you decided not to show us.
All of them can run at the same time without inturrupting each other.
because each thread handles different instance, there's no need for them to wait to what so ever synconized method.

Is synchronized "deep" in java?

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.

Am I properly implementing Java's synchronized construct?

I'm kind of confused about how to implement synchronized blocks in Java.
Here is an example situation:
public class SlotWheel extends Thread implements ActionListener
{
private int currentTick; // This instance variable is modified in two places
private synchronized void resetCurrentTicks()
{
currentTick = 0;
}
private synchronized void incrementCurrentTicks()
{
++currentTick;
}
public void actionPerformed(ActionEvent e)
{
resetCurrentTicks();
}
}
While the program is running, it's possible that a user clicks a button which invokes actionPerformed which then calls resetCurrentTicks. At the same time, the running thread is calling incrementCurrentTicks on each loop iteration.
Because I'm still new to Java and programming, I'm not sure if my implementation is protecting currentTick from becoming corrupted.
I have this feeling that my implementation would only work if incrementCurrentTicks were to be called in actionPerformed and in the running thread, but because I'm manipulating currentTick from different methods, my implementation is wrong.
Looks ok.
See http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
It is not possible for two invocations of synchronized methods on the same object to interleave
Of course you should consider whether it is the GUI thread trying to mess with the ticks or not. In your simple case it's probably ok, but in a more complex case you might want to push the "work" out of the GUI thread.
Your instincts are correct. It is difficult to synchronize access to class properties consistently across multiple methods. Rather than attempting to do so, I would recommend you take a look at java.util.concurrent.atomic.AtomicInteger. It provides you with safe, concurrent access to the underlying property without writing and testing alot of boilerplate code.
Incorporating it into your code, you would end up with something like this:
public class SlotWheel extends Thread implements ActionListener {
private AtomicInteger currentTick = new AtomicInteger();
private void resetCurrentTicks() {
currentTick.set(0);
}
private void incrementCurrentTicks() {
currentTick.incrementAndGet();
}
public void actionPerformed(ActionEvent e)
{
resetCurrentTicks();
}
}
First off, Java guarantees that "scalar" values -- integers, chars, floats, etc -- are atomic in themselves in that you cannot simultaneously modify such a value and get a mixture of the two sources. You're guaranteed to get one value or the other of two "simultaneous" modifications. You can, however, get an inconsistent result from, eg, x++, since two threads may attempt to simultaneously increment x and possibly only one increment might occur. (OTOH, two threads simultaneously performing x = 7; will obviously not interfere with each other -- simultaneous access does not cause an explosion or anything.)
Next, understand that the synchronized keyword is used in two slightly different contexts -- as a method modifier and as a block modifier. There is some modest difference between the two.
When used as a block modifier you say synchronized(object_ref) {some block}. In this case the synchronized statement gets a lock on the object identified by object_ref and all other syncronized statements that might simultaneously attempt to execute referencing the same object will be held off while the current statement finishes its block.
When you use it as a method modifier, the function is the same except that, for a non-static method, the "this" object is the one that is locked, and the entire method is is "protected" by the lock.
(For a static method, on the other hand, the Class object is locked -- a slightly special case, equivalent to synchronized(ClassName.class){some block} as a synchronized block.)
It's important to understand that for two synchronized blocks or methods to be prevented from simultaneously executing they must be referencing, as their synchronizing object, the same object, not simply one of the same class.
You are correct, in that it is not safe. However, you can simply synchronize on any Object in scope, and remove "synchronized" from the method definition
public class MyThread {
private Object lock = new Object();
private int counter;
protected void threadMetod() {
synchronized (lock) {
counter++;
}
}
public void otherReset() {
synchronized (lock) {
counter = 0;
}
}
}

Multiple object locks in Java?

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).

Synchronizing for the formal parameters in java

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.

Categories

Resources