Мультиплексирование С# 5.0 async через пул потоков - потокобезопасность?

Это может показаться немного сумасшедшим, но это подход, который я рассматриваю как часть более крупной библиотеки, если я могу быть уверенным, что это не вызовет странного поведения.

Подход:

Запустите асинхронный код пользователя с SynchronizationContext, который отправляется в пул потоков. Код пользователя выглядит примерно так:

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

Я не уверен, будет ли доступ к someState потокобезопасным. Хотя код будет работать в одном "потоке", так что операции, фактически, полностью упорядочены, его все равно можно разделить на несколько потоков под капотом. Если мое понимание правильное, заказ должен быть безопасным на x86, и поскольку переменная не является общей, мне не нужно беспокоиться о оптимизации компилятора и т.д.

Что еще более важно, я обеспокоен тем, будет ли это гарантировано потокобезопасным в моделях памяти ECMA или CLR.

Я абсолютно уверен, что мне нужно будет вставить барьер памяти перед выполнением очереди в очереди, но я не полностью уверен в своих рассуждениях здесь (или что этот подход может быть неработоспособным по совершенно разным причинам).

Ответ 1

Об этом говорится в разделе комментариев async/await FAQ:

TPL включает в себя соответствующие барьеры при постановке задач в очередь и в начале/в конце выполнения задачи, чтобы значения были соответственно видимыми.

Поэтому никаких явных барьеров не требуется.