6 comments

  • Groxx2 hours ago
    To be pedantic (which I feel is fair because it&#x27;s a concurrency question about possibilities):<p>&gt;<i>If we run P and Q concurrently, with ‘n’ initialized to zero, what would the value of ‘n’ be when the two processes finish executing their statements?</i><p>It depends a lot on the observer of `n` and what relationship it has with P and Q. Which isn&#x27;t defined.<p>E.g. a trivial boundary-answer is that it can be 0, if nothing guarantees that P&#x27;s and Q&#x27;s threads&#x27; memory reaches the `n`-observer&#x27;s thread. This is somewhat common if you try to synchronize via `sleep`, because that usually doesn&#x27;t guarantee anything as all.<p>We also don&#x27;t know the computer architecture. We can probably assume at least one byte moves between memory levels atomically, because basically every practical system does that, but that doesn&#x27;t have to be true. If <i>bits</i> move between memory levels independently, this could observe <i>31</i>, because it can be any combination of the bits between `00000` and `10100`, which includes `01011` -&gt; there can be a `1` in any position, including all positions, so you can observe a number that was <i>never</i> assigned. (IRL: multi-word values and partial initializations can do this, e.g. it&#x27;s why double-checked locking is flawed without something to guarantee initialization completes before the pointer is exposed)
  • fjfaase2 days ago
    This implicitely assumes atomic assignments, meaning that during an assignment all bits representing a value are transfered in one atomic unit. This sounds a bit trivial, but if one would be working with large integers that are stored in multiple memory words, it is less trivial.<p>I think it is possible to implement locking with only atomic assigments.
    • bcoates3 hours ago
      Yeah, looking at the code my &#x27;intuition&#x27; was &quot;this is a classic data race, the program is broken&quot; not &quot;somewhere between 10 and 20&quot;.<p>I suppose if you assume all global accesses are atomic, it&#x27;s a good demonstration that atomic operations don’t compose atomically (even in trivial cases) and aren&#x27;t particularly useful as concurrency primitives.
  • tombert2 hours ago
    This was fun to port over to PlusCal to verify it myself:<p><pre><code> EXTENDS Naturals, Sequences (*--algorithm StateStore { variables n = 0; completions = &lt;&lt;&gt;&gt;; define { Invar == Len(completions) = 2 =&gt; n # 2 } fair process (thing \in {&quot;p&quot;, &quot;q&quot;}) variables i = 0, temp = 0; { Loop: while (i &lt; 10) { First: temp := n + 1; Second: n := temp; Last: i := i + 1; }; Complete: completions := Append(completions, 1) } }*) </code></pre> (I acknowledge that this isn&#x27;t the most elegant Pluscal but I think it is a roughly accurate?)
  • dtgriscom2 hours ago
    Seems pretty clear that the result could be anything from 1 to 20.<p>(Assumes atomic assignments, as noted by someone else.)
  • Izikiel433 hours ago
    The intuition I developed over the years says that result is unknown, it&#x27;s a race condition, all bets are off. Specially since doing N+1.
  • lincpa2 hours ago
    [dead]