Card 08/ 09

ExerciseDifficulty: Advanced1 min

Four Classes: Which Are Safe and Which Only Look It

Four classes shared between threads. Decide for each whether it is safe, and if not, name the gap. All four before the reveal.

java
// 1
class A { private int n; synchronized void inc() { n++; } int get() { return n; } }

// 2
class B { private static int n; static synchronized void inc() { n++; }
          synchronized int get() { return n; } }

// 3
class C { private final AtomicInteger n = new AtomicInteger();
          void inc() { n.incrementAndGet(); } int get() { return n.get(); } }

// 4
class D { private final List<String> xs = Collections.synchronizedList(new ArrayList<>());
          void addIfAbsent(String s) { if (!xs.contains(s)) { xs.add(s); } } }
Which of the four are safe?
Each class, the verdict, and the gap
Safe?The gap
1Noget takes no lock, so it can read a value the last increment never published
2Noinc locks the class and get locks the instance — two different locks
3YesBoth operations go through the atomic, which handles exclusion and visibility
4Nocontains and add are each atomic and the sequence between them is not

Number two is the one that looks most thorough. Every method carries the keyword, and no two threads are ever excluded from each other, because the locks are different objects.

Number four is the shape from the previous exercise and from the money transfer. Where a class needs two calls to be one operation, the safety has to live in whoever is making them.