Out of Thin Air Safety

前端 未结 2 1330
夕颜
夕颜 2021-01-15 05:27

Java Concurrency in Practice explains this concept:

When a thread reads a variable without synchronization, it may see a stale value, but at least i

2条回答
  •  暖寄归人
    2021-01-15 05:52

    "Out-of-thin-air safety" is indeed a much weaker guarantee than e.g. "sequential consistency", but in some sense one might call it "strong." Namely, if your system provides OOTA-safety, you can reason about your programs much better than if your system didn't provide it. If you're using a system that doesn't provide OOTA-safety, you're basically screwed.

    Hans Boehm and Brian Demsky recently wrote a paper on the topic titled "Outlawing ghosts: avoiding out-of-thin-air results" (PDF available on ACM.org). They give some really good examples of how a non-OOTA-safe system might work, and what kinds of bugs might crop up in such a system.

    The basic idea is that some systems are allowed to do speculative execution, including speculative stores to memory (cache) which can later be undone if the system's speculation turns out to be incorrect. This works great in single-threaded systems, but in multi-threaded systems it is possible for two threads' speculations to feed on each other, creating a "runaway rumor mill": Processor A believes that x=42 because Processor B speculatively stored 42 there, but Processor B only stored x=42 because Processor A told it that y=17... but Processor A was merely speculating based on the assumption that x=42!

    void rivera() {                 void lemon() {
        if (x == 42) {                  if (y == 17) {
            y = 17;                         x = 42;
        }                               }
    }                               }
    

    A "non-OOTA-safe" system might rewrite these methods to look like (in pseudo-Python-Javascript syntax, sorry)

    void rivera() {
        assert(y not in cache);  // for the sake of argument
        cache.y = 17;  // for the sake of speed, speculatively report that y=17
        if (x not in cache) {
            cache.x = x;  // meanwhile, slowly fetch the real value of x
        }
        if (cache.x != 42) {
            delete cache.y;  // discard the earlier, speculative write
        }
        // and then later write cache.y back into the y in main memory
    }
    

    You can see how it would be a huge problem if lemon() trusted rivera()'s speculative report that cache.y = 17 and vice versa. We could end up, after both methods have completed, with the situation that x=42 and y=17 even when neither of them started out that way!

    I know people usually rely on time-travel paradox metaphors to describe how the values 42 and 17 end up in main memory "out of thin air", but I think the cable-news metaphor is more accurate. ;)

提交回复
热议问题