Thread-Safe Counter
Problem
Design a Counter that stores one signed integer. One shared instance may be accessed by several threads, and every public method must remain correct when calls overlap.
Requirements
- Initial state. Each
Counterowns an independent value that starts at0. - Increment.
incrementatomically adds1and returns no value. - Decrement.
decrementatomically subtracts1and returns no value. The value may become negative. - Read. The read method atomically returns the current value without changing it.
- Concurrent order. Calls on one shared instance are linearizable: every completed call appears to take effect at one point between its start and finish. This order must preserve call order inside each thread.
- Progress. A call may wait while another call accesses the counter, but it must not wait for a future call or an external event and must not deadlock.
API
| Signature | Returns | Behavior |
|---|---|---|
Counter() | Not applicable | Creates an independent counter whose value is 0. |
increment() | No value | Atomically adds 1. |
decrement() | No value | Atomically subtracts 1, including when the current value is 0 or negative. |
Python and C++: get_count()Java: getCount() | Signed integer | Returns one atomic view of the current value without changing it. |
All methods take no arguments and report no domain errors.
Examples
| Step | Operation | Result |
|---|---|---|
| 1 | Counter() | The counter value is 0. |
| 2 | increment() | The counter value becomes 1. |
| 3 | increment() | The counter value becomes 2. |
| 4 | Read | Returns 2. |
| 5 | decrement() | The counter value becomes 1. |
| 6 | Read | Returns 1. |
If one thread performs 1,000 increments while another performs 1,000 decrements, a read after both threads finish returns 0.
Constraints
- .
- .
- Every observed value fits in a signed 32-bit integer.
- Each method must perform work, excluding time spent waiting to access shared state.
- The implementation must not use external storage, network calls, sleeps, or process-wide global state.
Notes
The judge shares one Counter instance among all threads in a testcase. Calls inside one thread keep their listed order. Calls from different threads may interleave in any order that satisfies the linearizability rule.