avoid 'read reads'
[web.git] / ralf / _posts / 2018-07-13-arc-synchronization.md
index 0994c3fd2ed87b9597977add54a4be7b1645c275..1ad8a4695fc2502ecdb75852aa879916dc5525be 100644 (file)
@@ -157,10 +157,10 @@ fn main() {
 {% endhighlight %}
 This program, finally, is free of data races and hence has no undefined behavior and is guaranteed to print "Hello World!".
 
-They key point is that *when an `Acquire` read reads from a `Release` write, an order is induced between these two accesses*.
+They key point is that *when a `load(Acquire)` reads from a `store(_, Release)`, an order is induced between these two accesses*.
 We also say that the two accesses *synchronize*.
 Together with the per-thread order, this means we have an order between the `DATA = Some(...)` in the first thread and the load of `DATA` in the second thread, through the accesses to `FLAG`.
-Intuitively, the `Release` write in the first thread "releases" everything that has been changed by this thread so far, and the `Acquire` read in the second thread then "acquires" all that data and makes it accessible for access later in this thread.
+Intuitively, the `store(_, Release)` in the first thread "releases" everything that has been changed by this thread so far, and the `load(Acquire)` in the second thread then "acquires" all that data and makes it accessible for access later in this thread.
 
 Now, most of the time a `Mutex` or `RwLock` is good enough to protect your data against concurrent accesses, so you do not have to worry about such details.
 (And, thanks to Rust thread safety guarantees, you never have to worry about such details in safe code!)
@@ -174,7 +174,8 @@ However, `Arc` is one of those cases where the overhead induced by an exclusive
 As such, you are going to find plenty of atomic accesses in [the source code of `Arc`](https://github.com/rust-lang/rust/blob/c0955a34bcb17f0b31d7b86522a520ebe7fa93ac/src/liballoc/sync.rs#L201).
 
 And it turns out, as Hai and Jacques-Henri noticed when attempting to prove correctness of [`Arc::get_mut`](https://doc.rust-lang.org/beta/std/sync/struct.Arc.html#method.get_mut), that there is one place where `Relaxed` as used as an ordering, [but it really should have been `Acquire`](https://github.com/rust-lang/rust/pull/52031).
-Discussing the exact details of the bug would probably fill another blog post (`Arc` is *really* subtle), but the high-level story is exactly like in our example above: Thanks to `Acquire`, an ordering is induced between the code that follows the `get_mut` and the code in another thread that dropped the last [`Weak`](https://doc.rust-lang.org/beta/std/sync/struct.Weak.html) reference.
+Discussing the exact details of the bug would probably fill another blog post (`Arc` is *really* subtle), but the high-level story is exactly like in our example above: Thanks to `Acquire`, an ordering is induced between the code that follows the `get_mut` and the code in another thread that dropped the last other `Arc`, decrementing the reference count to 1.
+The PR that fixed the problem contains [some more details in the comments](https://github.com/rust-lang/rust/pull/52031/files).
 With `Relaxed`, no such ordering is induced, so we have a data race.
 To be fair, it is very unlikely that this race could lead to real misbehavior, but I am still happy to know that we now have a proof that `Arc` is mostly[^1] correctly synchronized.