You are right, it is not obvious.
Basically, it's a question of whether the channel behaves like a
Relaxed memory ordering, or like a
Acquire ordering, where these ordering names come from the
Ordering enum used with atomic integers. With
Relaxed, you can't rely on it, but with
Acquire, you can.
I can make an analogy to another form of "message passing" where you absolutely would expect analogous behavior. Consider this:
shared_mem = new_value;
in one thread, and
let new_value = shared_mem;
in the other. Here, I call the
unlock methods in the style you would see in C or C++, to make the analogy more clear. In the above case, you would absolutely expect that, if the second thread starts to try to acquire the lock while the first thread has the lock, the second thread will see whatever value the first thread wrote to the shared memory.
Here the "message" is that the lock is unlocked, and the blocking
.lock() call corresponds to the blocking
.recv() call in the original post.
Of course, this requires knowing that crossbeam actually corresponds to
Acquire orderings. See e.g. this comment from conversations regarding the issue I linked earlier with some other channel.