0

The paper C++ and the Perils of Double-Checked Locking by Scott Meyers and Andrei Alexandrescu describes the case when threads running on different cores may not see the same values of shared variables:

Suppose you’re on a machine with multiple processors, each of which has its own memory cache, but all of which share a common memory space. Such an architecture needs to define exactly how and when writes performed by one processor propagate to the shared memory and thus become visible to other processors. It is easy to imagine situations where one processor has updated the value of a shared variable in its own cache, but the updated value has not yet been flushed to main memory, much less loaded into the other processors’ caches. Such inter-cache inconsistencies in the value of a shared variable is known as the cache coherency problem.

Suppose processor A modifies the memory for shared variable x and then later modifies the memory for shared variable y. These new values must be flushed to main memory so that other processors will see them. However, it can be more efficient to flush new cache values in increasing address order, so if y’s address precedes x’s, it is possible that y’s new value will be written to main memory before x’s is. If that happens, other processors may see y’s value change before x’s.

On the other hand, I know that processors maintain a coherent view of the data values in multiple caches by means of coherence protocols, which can write-update or write-invalidate the copies of shared data in other cores. According to the Wikipedia, two clients must never see different values for the same shared data. Is it guaranteed?

If coherence protocols ensure that two cores will always see the same value of a shared variable, how is it possible that the situation described in the paper occurs?

mentalmushroom
  • 2,261
  • 1
  • 26
  • 34
  • not unless you're using `std::atomic` I think? – Alan Birtles Mar 11 '23 at 16:59
  • See [std::memory_order](https://en.cppreference.com/w/cpp/atomic/memory_order) – Richard Critten Mar 11 '23 at 17:10
  • And [Memory model](https://en.cppreference.com/w/cpp/language/memory_model). – Richard Critten Mar 11 '23 at 17:30
  • @RichardCritten Those links basically say the same: when multiple threads simultaneously read and write to several variables, one thread can observe the values change in an order different from the order another thread wrote them, but that IMO contradicts the statement from the Wiki, that two clients must never see different values for the same shared data. – mentalmushroom Mar 11 '23 at 17:40
  • You need the barriers described in the links above, plus the semantic meaning (of the barriers) to C++ the language. I would trust the above links more than Wikipedia to accurately describe the C++ memory model. You might also like to read [What cache coherence solution do modern x86 CPUs use?](https://stackoverflow.com/questions/62114759/what-cache-coherence-solution-do-modern-x86-cpus-use), note that the C++ Standard also applies to architectures with a more relaxed memory model eg ARM. – Richard Critten Mar 11 '23 at 17:57
  • Just a general note: The article is from 2004 and since C++11 what it says about C++ isn't really relevant anymore. Also, the Wikipedia article states what is usually understood as "cache coherency". It does not make a claim that a processor architecture _has to_ behave that way (even if they do in practice). C++ technically only requires cache coherency for `std::atomic` objects. – user17732522 Mar 11 '23 at 18:21
  • CPUs can work more efficiently if the caches are _not_ required to be "coherent" while they are working on their own, private data. We only need "coherence" when accessing _shared_ data. So how does the hardware know what is shared and what is not? That's where the [_memory barriers_](https://en.wikipedia.org/wiki/Memory_barrier) referenced by comments above come in to play. – Solomon Slow Mar 11 '23 at 20:41
  • @SolomonSlow Correct me if I am wrong, but I thought that coherence protocols are used internally by CPUs regardless of memory barriers. And if it is true, they must eliminate the case when two CPUs see different values for the same shared memory, according to the Wiki. So that was my question whether coherence protocols really guarantee it or the Wiki is not quite correct. – mentalmushroom Mar 12 '23 at 12:39
  • I am not a computer architect. (That's why I haven't posted an "answer.") I probably don't know the exact words and phrases that an architect would use to describe this, but I'm pretty sure that typical SMP computer hardware does _not normally_ "ensure that two cores will always see the same value of a shared variable." I do not know what actual goals "cache control protocols" try to achieve in the absence of any "memory barrier" instructions, but if you want two _threads_ to see a consistent view of shared variables, then those threads will need to use memory barriers. – Solomon Slow Mar 12 '23 at 13:31

0 Answers0