We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Fearless Concurrency: Threads, Channels, Shared State step 12 of 24
Release a read guard before acquiring a write lock
Repair the locking logic in a shared accumulator. Each worker reads an
RwLock<Option<u64>>, releases its read guard, then takes a write guard to
update the value.
pub fn get_or_init_shared(initial: Option<u64>, ops: Vec<u64>, workers: usize) -> u64
Start the shared cell at initial. For each operation x, initialize an
empty cell to Some(x), or add x to its existing value. Process every
operation exactly once. Return the final value, using 0 if the cell is
still empty. Treat zero workers as one.
Keep the supplied thread setup, chunking and joins. Replace the starter's wildcard read with a boolean recording whether the cell was empty. Release the read guard before requesting the write lock, then check the cell again under the write guard before initializing it.
Inputs have a total that fits in u64. Since all additions are nonnegative,
the expected result is initial.unwrap_or(0) + sum(ops) regardless of worker
order. For example, None with [1, 2, 3, 4] returns 10; Some(100) with
[1, 2, 3] returns 106. Empty operations return the initial value or zero.
When a guard releases its lock
Dropping a lock guard releases the lock. The starter writes:
let _ = shared.read().expect("lock poisoned");
This creates a temporary guard and drops it at the end of the statement.
It does not protect the later update. Rust's deny-by-default
let_underscore_lock lint rejects this spelling.
Changing _ to _guard creates a named binding that normally lives to the
end of its scope. That is also wrong here: requesting a write lock while
still holding the read guard can deadlock or panic. It is not a supported
way to upgrade a standard-library read lock.
Instead, copy out the observation and let the temporary guard drop:
let needs_init = shared.read().expect("lock poisoned").is_none();
// The read guard is gone; needs_init is an owned bool.
let mut w = shared.write().expect("lock poisoned");
This statement creates a new temporary. Do not generalize it to
let _ = existing_guard;: a wildcard does not move and drop an existing
named guard. Use drop(existing_guard) or a smaller scope when you need
to release that guard explicitly.
Recheck after acquiring the write lock
Another worker can update the cell after your read guard drops.
needs_init describes an earlier observation, not necessarily the current
state. Initialize only if the cell is still empty under the write lock;
otherwise add to the value now stored there. Using a stale observation to
overwrite the cell would lose another worker's contribution.
The read phase is a learning requirement here, not a performance fast path: every operation still takes the write lock. For this accumulator alone, a single write-lock acquisition would be simpler. The exercise practices how to release a read guard and revalidate an observation before updating.
Temporary scope matters
A guard created in a match scrutinee can remain alive through the selected
arm. Trying to acquire the same lock inside that arm can block progress.
Rust edition 2024 shortens a temporary's scope in an if let condition when
the pattern fails: it is dropped before entering else. A successful match
can still keep the guard alive through the then branch. This change does
not make every lock acquisition inside an if let safe. A separate statement
or explicit scope makes the intended release point easier to see.
Also release guards before joining workers that need the same lock. A join waits for the worker to finish; holding its required lock while waiting prevents that from happening.
A timeout can indicate a deadlock, but is not proof of one. Inspect guard scopes, lock acquisition order and which workers each join waits for.
Loading visualization…
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.