0

Given:

public class NamedCounter{ 

 private final String name; 

 private int count; 

 public NamedCounter(String name) { this.name = name; } 

 public String getName() { return name; } 

 public void increment() { count++; } 

 public int getCount() { return count; } 

 public void reset() { count = 0; } 

}

Which three changes should be made to adapt this class to be used safely by multiple threads? (Choose three.)

A. declare reset() using the synchronized keyword

B. declare getName() using the synchronized keyword

C. declare getCount() using the synchronized keyword

D. declare the constructor using the synchronized keyword

E. declare increment() using the synchronized keyword

Answers are A, C, E. But I don't understand why. According to synchronized keyword only used for manipulation operations. So why answer C?

This question comes from SCJP dumps.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • You need thread safety (synchronization) for any values which *can be mutated,* which includes `count`. – VGR Nov 10 '16 at 18:20
  • Incrementing a variable is not thread-safe. It requires a load and a store operations, and a thread running on another CPU could do its own load or store on the same memory location interleaved between those operations. – dammina Nov 10 '16 at 18:40

1 Answers1

0

The JVM uses the synchronized keyword to tell it when a variable's contents need to be made visible across threads. In the posted example not only is the increment method unsafe (the postincrement operator takes multiple steps to act, so that another thread can interfere with it while the increment is in progress) but all the methods that touch the count variable -- increment, reset, and getCount -- need the synchronized keyword to indicate that the count variable could be changed in another thread. Otherwise the JVM could perform optimizations like caching the value or eliminating the bytecode altogether, because it is free to reason about the code without taking into account the possibility of multithreaded access.

There are alternatives to synchronized here; for instance an AtomicInteger would work too, using it for count would make sure the value would change atomically and would be accessed in a way that is visible to all threads. But as the question is worded answers A, C, and E are all necessary.

Answer D is wrong because declaring a constructor as synchronized isn't valid syntax, and if it was valid it wouldn't accomplish anything for you. Synchronization protects against sharing across threads, but the constructor call doesn't share anything so there's nothing to protect.

Answer B is wrong because the name is an immutable object passed in as a constructor argument and assigned to a final instance member; since it is published safely and cannot change, synchronization is unnecessary.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276