0

I got to know that to make the program thread-safe, it is recommended to use synchronized methods or blocks of code. The doubt is how the below code snippet will make the program thread-safe? What is happening behind the scenes?

public class MyCounter
{
    private int count = 0; // count starts at zero

    public synchronized void setCount(int amount)
    { 
        count = amount;
    }

    public synchronized int getCount()
    {
        return count;
    }
}
Rahul
  • 15,979
  • 4
  • 42
  • 63
Aajan
  • 927
  • 1
  • 10
  • 23
  • Making code thread safe is not a simple matter of sprinkling "synchronized" around. Understanding even the basics requires a tutorial, which would be too long for this site. – Raedwald Mar 13 '16 at 13:34

3 Answers3

6

The doubt is how the below code snippet will make the program thread-safe?

The key thing here is that each java object has an implicit monitor associated with it and only one thread can enter the object monitor at any point of time and other threads that are trying to enter this monitor will be in queued either entry set or wait set.

And when a thread tries to executes a method that is marked as synchronized it is should get the ownership of the implicit monitor before executing the code in that method.

In your case you have two methods and both marked as synchronized. Since with the synchronized keyword only one thread will be able get hold of the object monitor that is needed to execute either of these methods, at any point only one thread can execute these synchronized method and thus they are thread-safe.

What is happening behind the scenes?

To understand how the object monitor, ownership, wait set and entry set work together, let us take the below picture that represents an implicit monitor that is unique for each java object. As we see, there are has two entry points to acquire the monitor i.e., from Entry Set or from Wait Set. For our discussion we will the flow only from Entry Set perspective and assume an empty Wait Set.

Java monitor entry set wait set

As the thread calls the synchronized method it is placed in the Entry Set.

  • If no thread currently owns the monitor and no other threads are waiting in the entry set, the thread becomes the owner of the monitor and starts executing the code. This is called the active thread.
  • Else, if there is another thread that is owning the monitor, the current thread is placed in the Entry set and will have to wait for its turn along with other already existing threads in Entry Set, if any.

While the current thread is waiting in the Entry Set,

  • The active thread will release the monitor when it is done with executing the code in the synchronized block. (other way of releasing is through wait() method that we will ignore for our discussion)
  • Subsequently, as the monitor is free now, the threads in the entry set will compete to acquire the monitor and one of them will get a chance.

NOTE : As indicated above, for the above discussion, we have assumed that there are no threads in the Wait Set for simplicity to keep discussion to the point. Wait Set comes into the picture with wait() and notify() calls.

I suggest and it is worth having a look at https://www.artima.com/insidejvm/ed2/threadsynchP.html for more detailed explanation on the monitors, entry set & wait set.

1

If we have Thread1, Thread2 and Thread3 where the first two waits to be release and the third is the one to release them, the order will go like this.

Thread1 enters and calls wait()
Thread2 enters and calls wait()
Thread3 enters and calls notifyAll()
Thread3 finishes, always

The waiting threads however has no specific order.
Which one is executed first, is completely random and has nothing to do with the order in which they called wait(). The thread calling notify(All) however will always finish before any waiting threads continues.

skypjack
  • 49,335
  • 19
  • 95
  • 187
Panky031
  • 425
  • 1
  • 5
  • 14
1
public synchronized void setCount(int amount)
{ 
        count = amount;  <-- *this operation is not atomic, and hence multiple thread execution may interleave resulting in race conditions*
}

Two steps take place when an assignment operator is executed:

  1. The expression on the right of the = is evaluated.
  2. The result of evaluation is assigned to the variable on the left of the =.

Note : the getter and setter need to be synchronized with the same monitor, as it also solves the issue of visibility. Without synchronized, if a thread calls the setter and another calls the setter, it is not guaranteed that second thread will see the updated value.

Visibility Demonstration

Community
  • 1
  • 1
Rahul
  • 15,979
  • 4
  • 42
  • 63