0

For this code in a multiple thread environment, is the synchronized(c) necessary?

SynchronizedCounter c = new SynchronizedCounter();
synchronized(c){
   c.increment();
   c.value();
}

public class SynchronizedCounter {
   private int c = 0;

   public synchronized void increment() {
     c++;
    }
   public synchronized void decrement() {
     c--;
   }
   public synchronized int value() {
     return c;
    }
}
ling
  • 1,555
  • 3
  • 18
  • 24

2 Answers2

1

It is needed if you want to make sure that when you call c.value() after c.increment(); you are getting the value + 1

To avoid the situation that another thread2 calls c.decrement() between the call of c.increment() and c.value() in thread1

iTech
  • 18,192
  • 4
  • 57
  • 80
  • 1
    So generally if a thread needs to call multiple methods in a sequence on an object and don't want other threads to interfere with it during that process, it should use local synchronization on individual object, regardless of whether the methods in that object are already sychronized or not. Is my understanding true? – ling Feb 16 '13 at 23:53
  • you can synchronize on individual operations like you did in each method, but that's not the same as creating a block of operations to be done without interference. – Ralf H Feb 16 '13 at 23:55
  • Synchronizing a method or a block ensures that it will be executed at once without interference from another thread. But to ensure this behavior on a group of `synchronized methods` you still need synchronization for the entire code block. – iTech Feb 16 '13 at 23:58
  • Then what about this situation? Suppose: c.increment() by Thread A, then a number of other operations occurs which have nothing to do with object c. Then finally c.value() at the end of the block. The two operations are not strictly in sequence. In this case, is it needed to put the big chunk of code in between c.increment() and c.value() in a synchonized block? – ling Feb 17 '13 at 00:04
  • If I understood you correctly, if the two operations are not `racing` on a shared resource `c` in this example, so no need for synchronization – iTech Feb 17 '13 at 00:13
  • So in this sense, there is no real "thread safe" class. External synchronization may be needed always. – ling Feb 17 '13 at 00:14
  • Hi, iTech, just assume Thread A needs to execute c.increment() and c.value() in a block, and it's unpredictable that other threads might take what actions on object C. So to be thread safe, the block sync is always needed. That's my question! Thanks. – ling Feb 17 '13 at 00:18
  • You should be aware that synchronization could decrease the program performance and create a bottleneck. So it should be used wisely when needed only. – iTech Feb 17 '13 at 03:59
1

If you want the getValue call to see the result of the increment, without intervening increment or decrement from another thread, you do need the synchronized(c).

This is a sufficiently common requirement that similar designs often return the new value from an increment or decrement call. See, for example, java.util.concurrent.atomic.AtomicInteger. It has methods such as incrementAndGet().

Incidentally, if you are really using this code, rather than just using it to illustrate your question, consider using AtomicInteger instead.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75