Real Red.
Real Red.

Reputation: 5039

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

Upvotes: 5

Views: 2676

Answers (6)

Matt Wonlaw
Matt Wonlaw

Reputation: 12443

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.

Upvotes: 1

iluxa
iluxa

Reputation: 6969

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.

Upvotes: 0

Paŭlo Ebermann
Paŭlo Ebermann

Reputation: 74810

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.

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 692073

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.

Upvotes: 2

Amir Raminfar
Amir Raminfar

Reputation: 34179

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.

Upvotes: 3

Brent Worden
Brent Worden

Reputation: 10994

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.

Upvotes: 0

Related Questions