Java

Lesson 08

Concurrency and shared state

Use concurrent primitives for shared state so check-then-act races do not appear under load.

Good Code

src/main/java/dev/review/cache/ProfileCache.java
public final class ProfileCache {
    private final ConcurrentMap<UserId, UserProfile> profiles = new ConcurrentHashMap<>();
    private final UserService users;

    public UserProfile get(UserId id) {
        return profiles.computeIfAbsent(id, users::loadProfile);
    }
}

Bad Code

src/main/java/ProfileCache.java
public class ProfileCache {
    private final Map<String, UserProfile> profiles = new HashMap<>();

    public UserProfile get(String id) {
        if (!profiles.containsKey(id)) {
            profiles.put(id, users.loadProfile(id));
        }

        return profiles.get(id);
    }
}

Review Notes

What to review

Good Code

The good version uses a concurrent map and makes the atomic operation explicit with computeIfAbsent.

Bad Code

The bad version uses a shared HashMap and a check-then-put sequence. Two threads can compute the same value, corrupt the map, or observe inconsistent state.

Takeaways

  • If multiple threads can touch a value, the code should show which primitive owns synchronization.