12

This may seem a little crazy, but it's an approach I'm considering as part of a larger library, if I can be reasonably certain that it's not going to cause weird behavior.

The approach:

Run async user code with a SynchronizationContext that dispatches to a thread pool. The user code would look something like:

async void DoSomething()
{
    int someState = 2;
    await DoSomethingAsync();
    someState = 4;
    await DoSomethingElseAsync();
    // someState guaranteed to be 4?
}

I'm not certain whether access to someState would be threadsafe. While the code would run in one "thread" such that the operations are, in fact, totally ordered, it could still be split across multiple threads beneath the hood. If my understanding is correct, ordering ought to be safe on x86, and since the variable isn't shared I won't need to worry about compiler optimizations and so on.

More importantly though, I'm concerned as to whether this will be guaranteed thread-safe under the ECMA or CLR memory models.

I'm fairly certain I'll need to insert a memory barrier before executing a queued piece of work, but I'm not totally confident in my reasoning here (or that this approach might be unworkable for entirely separate reasons).

ShZ
  • 6,518
  • 1
  • 26
  • 22
  • 5
    It is a local variable. How can it not be threadsafe? IOW what makes you think it can be changed in another thread? (Unless you are passing a reference to it somewhere that is not being shown ie `ref` or as a captured variable). – leppie Nov 13 '12 at 06:08
  • 4
    From what I understand, `await` transforms the following code into a continuation which gets executed on the current `SynchronizationContext` when the underlying `Task` finishes. If this is dispatching to a thread pool, then the continuation can run on a different thread. It won't run *concurrently* in any way, but I'm not sure whether changes to `someState` would be guaranteed to be visible if the continuation executes on a different physical thread. – ShZ Nov 13 '12 at 06:34
  • 2
    This is a great question, which a lot of people don't even know to ask. – Stephen Cleary Nov 13 '12 at 13:12

1 Answers1

10

This is answered in the comments section of the async / await FAQ:

TPL includes the appropriate barriers when tasks are queued and at the beginning/end of task execution so that values are appropriately made visible.

So no explicit barriers are necessary.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810