kannanrbk
kannanrbk

Reputation: 7134

How synchronization block works?

Bug Code

public class Scheduler {
 private Object lock = new Object();

 private int interval;
 private int period;

 public Scheduler(int interval , int period) {
   this.interval = interval;
   this.period = period;
 }

 public synchronized void  setInterval(int interval) {
     this.interval = interval;
 }

 public synchronized void setPeriod(int period) {
       this.period = period;
 }

 public void updateScheduler(int interval , int period) {
    synchronized(lock) {
      setPeriod(period);
      setInterval(interval);
    }
 }

}

I have some threadsafe issues in my code to find those , I ran thread safe eclipse plugin in my project.

Thread Safe Report

  1. Mixed synchronization in Scheduler Class

    Bug Description

    For the avoidance of dataraces, it is important that fields that are accessed concurrently are consistently guarded by a common lock. If the same lock object is not held each time a field is accessed, a datarace can occur.

Fixed Code

public class Scheduler {
     private Object lock = new Object();

     private int interval;
     private int period;

     public Scheduler(int interval , int period) {
       this.interval = interval;
       this.period = period;
     }

     public void  setInterval(int interval) {
         synchronized(lock) {
            this.interval = interval;
         }
     }

     public void setPeriod(int period) {
          synchronized(lock) {
             this.period = period;
          }
     }

     public void updateScheduler(int interval , int period) {
        synchronized(lock) {
          setPeriod(period);
          setInterval(interval);
        }
     }

    }

I tested this code , it works fine. My question is , I am invoking setPeriod and setInteval from inside of updateScheduler. When updateScheduler is called , the object lock is already locked then i am calling setInterval and updateScheduler but the lock was not released. I am expecting the code will end up in dead lock. But , it is not happened why?

Upvotes: 0

Views: 118

Answers (2)

Toby
Toby

Reputation: 9803

There's only one monitor being locked in the fixed code (lock), so deadlock isn't possible.

To fix the original code, you could have also synchronised the updateScheduler method rather than use the lock object. It would achieve the same thing.

In terms of your question, Java locking is "reentrant", that means, when a "locked" piece of code tries to "lock" it again (i.e., using the same monitor), it understands its the same monitor and so doesn't block/wait for it to be unlocked. It knows it already "owns" it. Make sense?

Upvotes: 3

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279890

The Java Language Specification says

A thread t may lock a particular monitor multiple times; each unlock reverses the effect of one lock operation.

So you can have nested synchronized blocks for the same object.

synchronized(lock) {
    synchronized(lock) {
        synchronized(lock) {
            // ad nauseam and within method calls
        }
    }
}

This is further explaining in the Java tutorial on Intrisic Locks and Synchronization

Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.

Upvotes: 3

Related Questions