Rajit s rajan
Rajit s rajan

Reputation: 595

Synchronization block in java

class Call {
  int count;

  public   void  increment() {
    for (int i = 0; i < 1000; i++)
        count++;
  }
}

class Caller implements Runnable {

  Call c;

  public Caller(Call c) {
    this.c = c;
  }

  @Override
  public void run() {
    // TODO Auto-generated method stub
        c.increment();
  }
}

class Calling implements Runnable {

  Call c;

  public Calling(Call c) {
    this.c = c;
  }

  @Override
  public void run() {
    // TODO Auto-generated method stub
    synchronized (c) {
        c.increment();
    }
  }
}

public class SynchronizedBlock {

  public static void main(String[] args) throws InterruptedException {
    Call call = new Call();
    Calling calling = new Calling(call);
    Caller caller = new Caller(call);

    Thread t1 = new Thread(caller);

    Thread t2 = new Thread(calling);
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println("caller:" + caller.c.count);
  }
}

Here have made increment method synchronized in 1 class and in other class i havent made it as synchronized. When i run the above code , it sometimes gives value of count less than 2000 .

As per my understanding, Since Calling class's object has already locked the object, so there is no need to synchronize in Caller class increment method.

Could you please help me in understanding the logic here.

Upvotes: 0

Views: 70

Answers (3)

mzc
mzc

Reputation: 3355

synchronized keyword in java means that lock will be acquired before entering the block and released after exit.

Since t2 acquires/releases the lock and t1 doesn't, there is effectively no synchronization going on. t1 just goes in the block whenever the CPU time is assigned to it.

t2 also always goes in the block without waiting because the lock is never acquired by t1.

--

If you synchronize the increment method your program will work correctly:

class Call {
  int count;

  public synchronized void increment() {
    for (int i = 0; i < 1000; i++)
        count++;
  }
}

After this change you can remove the synchronized block from t2.

Upvotes: 1

flakes
flakes

Reputation: 23684

What's probably happening when you get the correct value of 2000, happens between the lines:

t1.start();
t2.start();

This is because the execution of public void increment(); is finishing in a single quantum, before the t2.start() line is even executed. A Thread Quantum is the time that the thread runs before a different thread can run on the processors core.

The first thread doesn't lock the object, and occasionally a single quantum will not encompass the entire execution of increment(), which leaves time for thread 2 to begin executing and working on the same object data. This will result in 2 copies of the variable count existing at the same time, competing for the same memory.

Try increasing the amount of increments for (int i = 0; i < 1000; i++) to some number like for (int i = 0; i < 10000000; i++). You will most likely see the application begin to fail more often.

Upvotes: 0

Jeffrey
Jeffrey

Reputation: 44808

Since Calling class's object has already locked the object, so there is no need to synchronize in Caller class increment method.

Your understanding is incorrect. In order for parallel actions on a variable to be deterministic, you must have some sort of synchronization in place on every access/modification to that variable**.

You need to synchronize in Caller as well.

**: This is a necessary but insufficient condition to guarantee determinism.

Upvotes: 1

Related Questions