Hone logo
Hone
Problems

Concurrent Counter with Multiple Writers and Readers

This challenge focuses on implementing a thread-safe counter using Go's synchronization primitives. Understanding and correctly utilizing mutexes and read/write mutexes is crucial for building robust concurrent applications. You'll be tasked with creating a counter that can be safely incremented by multiple goroutines and read by others, ensuring data integrity.

Problem Description

You need to implement a Counter struct that provides thread-safe increment and get operations. The Counter should be initialized with a starting value of 0. Multiple goroutines should be able to concurrently increment the counter, while other goroutines can safely read the current value. The implementation must prevent race conditions and ensure that reads always reflect the latest value after an increment.

Key Requirements:

  • Thread-Safe Increment: The Increment() method should atomically increment the counter's value. Multiple goroutines calling Increment() concurrently should not lead to lost updates.
  • Thread-Safe Get: The Get() method should return the current value of the counter without data races.
  • Read/Write Mutex Optimization: Use a sync.RWMutex to optimize read operations. Multiple readers should be able to access the counter concurrently, while writers (incrementing) should have exclusive access.
  • Initialization: The Counter struct should be initialized with a starting value of 0.

Expected Behavior:

  • Multiple goroutines incrementing the counter concurrently should result in the counter's value accurately reflecting the total number of increments.
  • Reading the counter's value should always return a consistent and up-to-date value, even when increments are happening concurrently.
  • The program should not panic due to race conditions.

Edge Cases to Consider:

  • High concurrency: Simulate a large number of goroutines incrementing and reading the counter simultaneously.
  • Rapid increments followed by reads: Test the scenario where increments happen very quickly, followed by a read operation.

Examples

Example 1:

Input:  Multiple goroutines concurrently calling Increment() 1000 times each, followed by a Get() call.  Let's say 5 goroutines each call Increment() 1000 times.
Output: 5000
Explanation: Each of the 5 goroutines increments the counter 1000 times, resulting in a total of 5000 increments. The Get() call should return this value.

Example 2:

Input: One goroutine increments the counter 100 times, another goroutine increments it 50 times, and then a third goroutine calls Get().
Output: 150
Explanation: The first goroutine increments the counter 100 times, and the second goroutine increments it 50 times. The Get() call should return the sum of these increments, which is 150.

Example 3: (Edge Case - High Concurrency)

Input: 100 goroutines concurrently calling Increment() 1000 times each, followed by a Get() call.
Output: 100000
Explanation:  Each of the 100 goroutines increments the counter 1000 times, resulting in a total of 100,000 increments. The Get() call should return this value, demonstrating the thread-safe nature of the implementation under high load.

Constraints

  • The Counter struct must be defined.
  • The Increment() method must take no arguments and return nothing.
  • The Get() method must take no arguments and return an int.
  • The implementation must use a sync.RWMutex.
  • The program should be able to handle at least 1000 concurrent increment operations without significant performance degradation.
  • The counter's initial value must be 0.

Notes

  • Consider using sync.WaitGroup to wait for all incrementing goroutines to complete before calling Get(). This will help ensure that all increments are reflected in the final value.
  • The sync.RWMutex allows multiple readers or a single writer. Think about how to leverage this for optimal performance.
  • Thorough testing with concurrent goroutines is essential to verify the correctness of your implementation. Use go test -race to detect potential race conditions.
Loading editor...
go