Hone logo
Hone
Problems

Concurrent Counter with Data Race Freedom in Rust

Rust's ownership and borrowing system are powerful tools for preventing data races at compile time. This challenge asks you to implement a thread-safe counter using Rust's concurrency primitives to ensure data race freedom. Understanding and utilizing these primitives is crucial for writing robust and reliable concurrent Rust programs.

Problem Description

You are tasked with creating a thread-safe counter that can be incremented by multiple threads concurrently. The counter must be protected against data races, meaning that multiple threads should be able to access and modify the counter without causing undefined behavior. You should achieve this using Rust's standard library concurrency features, specifically Mutex and Arc.

What needs to be achieved:

  • Implement a Counter struct that holds an integer representing the counter value.
  • Provide a increment() method that increments the counter value.
  • Ensure that the increment() method is thread-safe, preventing data races when called from multiple threads.
  • Provide a value() method that returns the current counter value.

Key requirements:

  • The counter must be accessible and modifiable from multiple threads simultaneously.
  • The implementation must be free of data races. Rust's borrow checker should not flag any potential data races.
  • The code should be concise and idiomatic Rust.

Expected behavior:

When multiple threads call increment() concurrently, the final counter value should be the sum of all increments. The value() method should return the correct, up-to-date counter value at any given time.

Edge cases to consider:

  • High contention: Many threads attempting to increment the counter simultaneously.
  • Thread creation and destruction: Threads starting and stopping while accessing the counter.

Examples

Example 1:

Input: Two threads, each calling `increment()` 1000 times.
Output: Counter value: 2000
Explanation: Each thread increments the counter 1000 times, resulting in a total of 2000 increments.

Example 2:

Input: Five threads, each calling `increment()` a different number of times (e.g., 10, 20, 30, 40, 50).
Output: Counter value: 150
Explanation: The sum of the increments from each thread (10 + 20 + 30 + 40 + 50) is 150.

Example 3: (Edge Case - High Contention)

Input: 100 threads, each calling `increment()` 1000 times.
Output: Counter value: 100000
Explanation:  Even with high contention, the counter should accurately reflect the total number of increments (100 * 1000 = 100000).

Constraints

  • The solution must use Arc and Mutex from the Rust standard library.
  • The solution must compile without warnings.
  • The solution should be reasonably efficient. While performance is not the primary focus, avoid unnecessary allocations or complex operations.
  • The Counter struct should be thread-safe.

Notes

  • Arc (Atomic Reference Counting) allows multiple threads to own shared, immutable data.
  • Mutex (Mutual Exclusion) provides exclusive access to shared, mutable data, preventing data races.
  • Consider how to combine Arc and Mutex to achieve thread-safe access to the counter.
  • Think about the ownership and borrowing rules in Rust and how they apply to concurrent access.
  • The goal is to demonstrate understanding of Rust's concurrency primitives and their ability to prevent data races.
Loading editor...
rust