Synchronization mechanism for an observable object
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
An observable object allows multiple observers to subscribe to state changes and receive notifications when the object is updated. In concurrent environments, multiple threads may modify the observable's state or subscribe/unsubscribe observers simultaneously, leading to race conditions, missed notifications, or ConcurrentModificationException errors. Synchronization mechanisms — locks, concurrent collections, copy-on-write patterns, and reactive frameworks — ensure thread-safe access to both the observer list and the observable's internal state.
Thread-Safe Observable in Java
CopyOnWriteArrayList creates a new copy of the internal array on every write (add/remove). Iteration is lock-free and safe even if observers are added or removed during notification. This is ideal when reads (notifications) far outnumber writes (subscribe/unsubscribe).
Synchronized Blocks Approach
The key pattern: take a snapshot of the observer list inside the synchronized block, then notify outside the lock. This prevents deadlocks where an observer's callback tries to modify the observable.
ReadWriteLock for Read-Heavy Workloads
ReadWriteLock allows multiple threads to read the value concurrently while ensuring exclusive access for writes. This improves throughput when getValue() is called much more frequently than setValue().
Python Thread-Safe Observable
Reactive Streams (Modern Approach)
Reactive frameworks like RxJava and RxPY encapsulate synchronization internally. Subscribers receive notifications on designated schedulers, eliminating manual lock management. This is the preferred approach for complex event-driven systems.
Common Pitfalls
- Notifying observers inside a synchronized block: If an observer's callback modifies the observable (adds/removes observers or changes the value), notifying inside the lock causes a deadlock or
ConcurrentModificationException. Always take a snapshot of the observer list inside the lock and notify outside it. - Using
ArrayListwithout synchronization: Iterating over anArrayListwhile another thread modifies it throwsConcurrentModificationException. UseCopyOnWriteArrayList, or synchronize and snapshot before iterating. - Holding locks during long-running callbacks: If observer callbacks perform I/O, network calls, or heavy computation, holding the lock during notification blocks all other threads from accessing the observable. Snapshot-and-notify-outside-lock is the standard pattern to avoid this.
- Forgetting
volatileor locks for the value field: Withoutvolatileor synchronization, changes to the observable's value may not be visible to other threads due to CPU cache coherency. Mark the fieldvolatileor always read/write it under a lock. - Observer memory leaks: If observers hold strong references and are never unsubscribed, the observable prevents garbage collection of observer objects. Use weak references (
WeakReferencein Java,weakrefin Python) or ensure explicit unsubscription when observers are no longer needed.
Summary
- Use
CopyOnWriteArrayListwhen subscribe/unsubscribe is rare but notifications are frequent - Use synchronized blocks with snapshot-and-notify-outside-lock for general-purpose thread safety
- Use
ReadWriteLockwhen reads (getValue) far outnumber writes (setValue) - Reactive frameworks (RxJava, RxPY) handle synchronization internally and are preferred for complex scenarios
- Always notify observers outside the lock to prevent deadlocks
- Use
volatileor locks for the observable's value field to ensure cross-thread visibility
Related reading
- Synchronization mechanisms in distributed system
- Synchronization of non-final field
- Synchronization vs Lock
- Synchronization vs Lock
- Synchronize actions in a distributed system
- Synchronize Data From Multiple Data Sources
- Synchronize two postgresql databases with current data using with bucardo
- Synchronizing a local Git repository with a remote one
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.