Nick Div
Nick Div

Reputation: 5628

What is the purpose of declaring a method synchronized in the following example

You can copy paste the below example to run on your local machine. I am learning MultiThreading and I came across this example online. I am confused as to why the method add(inside class Counter) would make a difference if declared synchronized, you can remove the keyword synchronized from it and it would not affect the end result so I am just wondering what's the purpose to be served by declaring it synchronized

class Counter {

    long count = 0;

    public synchronized void add(long value) {
        this.count += value;
        System.out.println(count + "-" + Thread.currentThread().getName());
    }
}

class CounterThread extends Thread {

    protected Counter counter = null;

    public CounterThread(Counter counter) {
        this.counter = counter;
    }

    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                Logger.getLogger(CounterThread.class.getName()).log(Level.SEVERE, null, ex);
            }
            counter.add(i);
        }
    }
}

public class Example {

    public static void main(String[] args) {
        Counter counter = new Counter();
        Thread threadA = new CounterThread(counter);
        Thread threadB = new CounterThread(counter);
        Thread threadC = new CounterThread(counter);

        threadA.start();
        threadB.start();
        threadC.start();
    }
}

Upvotes: 2

Views: 67

Answers (3)

EJK
EJK

Reputation: 12527

Declaring the class as synchronized means that whatever thread wants to execute the method must first acquire the current object's lock. The object has exactly one lock and only the thread that has obtained it can execute the method. Other threads must wait until the lock-holding thread is done. Upon completion of the method, the executing thread releases the lock.

In short. the synchronized keyword ensures that at any given time, only one thread can execute the method.

Synchronization is important on classes where (a) the system is multi-threaded; (b) The class has instance variables that can be changed within the method. Multi-threading issues typically occur when two or more threads are executing the same method simultaneously. One thread can change an instance variable based on its inputs, and those changes are seen by the other thread.

In this particular example, a problem could arise with the instance variable count. If one thread sets it to say 5, a second thread could come along and set it to 10. When the first thread then executes the System.out.println call, it prints a value of 10 - which is unexpected behavior.

Upvotes: 4

Bohemian
Bohemian

Reputation: 424973

The reason that making the add() method synchronised is important is that this line:

this.count += value;

Is not an atomic action. It a really compiles as this (or similar):

long c = count;
c = c + value;
count = c;

Which should be pretty obviously not threadsafe.

Upvotes: 3

Brett Kail
Brett Kail

Reputation: 33936

The synchronized keyword prevents threadA, threadB, and threadC from executing the operations at the same time. It's important to understand that this.count += value is internally implement as three operations:

  1. read count field
  2. add value
  3. write count field

If you remove the synchronized keyword, then you can imagine the following sequence of events:

  1. threadA reads count field (0)
  2. threadB reads count field (0)
  3. threadA adds value to count (count=0 from #1 + value=1 for example)
  4. threadB adds value to count (count=0 from #2 + value=1 for example)
  5. threadA writes count field (1 from #3)
  6. threadB writes count field (1 from #4 (!), so the write operation in #5 is lost)

Upvotes: 4

Related Questions