Card 08/ 09

ExerciseDifficulty: Advanced1 min

Practice: Deciding Which Classes Are Thread-Safe

Four classes that all look guarded: find the gap in each one that is not.

A class is thread-safe only if every read and write of its shared state is protected by the same lock or an atomic operation, and every sequence that must be one operation is protected as a whole. For each of the four classes below, decide whether it is safe and, if not, name the gap, all four before you open the answer.

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 kept apart, because the locks are different objects.

Number four is the check-then-act shape again. Where a class needs two calls to be one operation, the safety has to live in whoever makes the calls.