Skip to content

← Concurrency with Threads and asyncio step 7 of 56

Easy Primitives

Fix a Counter That Loses Updates

Several threads record page views on one shared PageViews counter, and the counter loses most of them. Run the starter code as it is. In the first test, eight threads record 25 views each, so expected is 200, but total comes back as 25.

Each call to record() reads the total, calls save_to_cache(), and writes the new total. While one thread is inside save_to_cache(), the others read the same old total, so their updates overwrite each other.

What to write

Make PageViews safe to share between threads:

  • Create one threading.Lock in __init__.
  • In record(), hold the lock across the read, the call to save_to_cache(), and the write.
  • In count(), read total while holding the same lock.

Keep the call to save_to_cache() inside record(), and do not change save_to_cache() or solve.

What the driver checks

solve starts threads threads. Each one calls record() views_per_thread times. When they have all finished, it returns:

  • total: the value of count().
  • expected: threads * views_per_thread.

The two must be equal. With zero threads or zero views, both are 0. With one thread there is no race, so that case passes even before you fix it.