fernandohur
fernandohur

Reputation: 7134

Disadvantages of nested synchronized blocks

Learning about threads and concurrency. Consider the following code:

class A {

  protected final Object lock = new Object();

  public void remove(Object obj){
    synchronized(lock){
      // remove the object
    }
  }

  public void add(Object obj){
    synchronized(lock){
      // add the object
    }
  }
}

This code is thread-safe in the sense that no two different threads can add or remove while one thread is in the process of adding or removing.

Now consider the following sublcass of A:

class B extends A {

  public void update1(Object original, Object newObj){
    remove(original);
    add(original); 
  }

  public void update2(Object original, Object newObj){
    synchronized(lock) {
      remove(original);
      add(newObj);
    }
  }

}

Class B must implement a thread-safe update method. Now, as far as I know update1 is not thread safe because the operation is not atomic, i.e. there is no synchronization between the execution of remove and add (correct me if wrong).

Is update2 the correct way to implement a thread-safe update method? Are there any disadvantages of having nested synchronized blocks over the same lock?

Upvotes: 4

Views: 1995

Answers (3)

Puneet
Puneet

Reputation: 113

The lock is re entrant unless you would be seeing deadlocks every where

Re-entrant lock is the lock which can be reaquired even if the lock is already attained by the same thread.

Why wont you provide the removeAndAdd in the Super class method if there is a scenario which must have remove and add atomic .

Make sure your lock object is marked private and final for security reasons.

Upvotes: 0

Stephan
Stephan

Reputation: 43013

The use of synchronized makes the whole object "locked": no other threads can call any methods while another thread is running one of the object synchronized methods.

This behavior can really slow some program.

As an alternative, you can use ReentrantLock.

Here is how it applies for the code in the post:

class A {
  protected final Lock lock = new ReentrantLock();

  public void remove(Object obj){
    lock.lock();
    try {
      // remove the object
    } finally {
       lock.unlock();
    }
  }

  public void add(Object obj){
    lock.lock();
    try {
      // add the object
    } finally {
       lock.unlock();
    }
  }
}

class B extends A {
  // ...

  public void update2(Object original, Object newObj){
     lock.lock();
     try {
        remove(original);
        add(newObj);
     } finally {
       lock.unlock();
     }
  }
}

Upvotes: -1

Marko Topolnik
Marko Topolnik

Reputation: 200138

Is update2 the correct way to implement a thread-safe update method?

Yes, it is. You have achieved atomicity and you are compatible with callers of the individual add and remove methods.

Are there any disadvantages of having nested synchronized blocks over the same lock?

No, because the locks are reentrant, meaning the second acquisition doesn't do anything more than remember that the lock was acquired once more, so it doesn't get released until two release actions are performed.

Upvotes: 10

Related Questions