1. 9

  2. 3

    I know it’s bad form to nitpick the introduction of an otherwise-great article which is itself an explanation of another great article, but something about the opening categorization of languages bothered me. To reword:

    1. Data races provoke undefined behavior
    2. Data races provoke object tearing, dirty reads, or other bugs common to data races
    3. Data races are not possible

    I’m not sure whether this is exhaustive. There should be at least one more family: languages where data races are possible, but do not result in bugs. In E, the only possible data race is when a promise resolves multiple times within a single turn, and E defines this case to cause an exception for whichever resolver loses. In Haskell, with the STM monad, data races become transactions and losing writers are able to retry until they succeed/win. In both languages, data races turn from a bug into a feature, because multiple resolvers/writers can cooperate to incrementally advance a distributed state. (Sure, the state is only distributed between threads, but sharing state between threads is hard!)

    1. 2

      I’m not familiar with the E language so I’m basing the following entirely on the description that you’ve provided above. If a promise resolves multiple times and this situation is reliably detected and turns into an exception then it sounds to me like there are no data races in E. If there were data races then I would expect undesirable things to happen. One result could be “silently” lost, or the result could change out from under you once you’ve observed it, etc.

      Is this a semantic problem where we’re not using the same definition of “data race”? I’m using the definition from https://docs.oracle.com/cd/E19205-01/820-0619/geojs/index.html

      A data race occurs when:

      • two or more threads in a single process access the same memory location concurrently, and
      • at least one of the accesses is for writing, and
      • the threads are not using any exclusive locks to control their accesses to that memory.

      If E can reliably detect the situation that you described then I would think that under the covers it must be using a lock or atomic memory operations in the implementation. If that’s correct then there would be no data races.

      Are you perhaps thinking of “race condition” instead of “data race”?

      1. 1

        E and Haskell are implemented with green threads. Perhaps this makes them unfair examples, since we would want to see them implemented with OS threads before believing my claims. Indeed, I think it is fair to say that data races aren’t possible in E. I gather that STM still works with OS threads, though it uses atomic compare-and-swap operations.

        Thanks for both your perspective and the link.