2016-03-13 5 views
2

В контексте this и this ранее заданные вопросы, а также принимая во внимание this answer мне интересно, если в следующем C# код доступа к локальным переменным захваченными должны быть синхронизированы.Доступ к захвачена локальных переменных одновременно

// Let’s say we have two classes Person and Animal that are immutable. 
// Then there is some code that instantiates and uses instances of these classes: 
public void SomeMethod() 
{  
    Person person = null; 
    Animal animal = null; 

    Parallel.Invoke(() => person = CreatePerson(), // some long running creation process 
                 () => animal = CreateAnimal()); // some long running creation process 

    // person and animal variables are used beyond this point in non-concurrent manner 
} 

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

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

Parallel.Invoke(() => Volatile.Write(ref person, CreatePerson()), 
       () => Volatile.Write(ref animal, CreateAnimal())); 

Update 1

Позвольте мне усложнять мой пример немного, и объяснить мой мыслительный процесс.

// Let’s say we have two classes Person and Animal that are immutable. 
// Then there is some code that instantiates and uses instances of these classes: 
public void SomeMethod() 
{ 
    Person person = CreatePersonLight(); // very fast creation process 
    Animal animal = CreateAnimalLight(); // very fast creation process 

    if (IsMonday()) 
    { 
     Parallel.Invoke(() => person = CreatePersonHeavy(), // some long running creation process 
         () => animal = CreateAnimalHeavy()); // some long running creation process 
    } 

    // person.Name and animal.Breed values are used beyond this point in non-concurrent manner 
} 

Насколько я понимаю, в этом коде задействованы три потока. Первый поток, который выполняет «SomeMethod», второй поток, который выполняет «CreatePersonHeavy», и третий поток, который выполняет «CreateAnimalHeavy».

Я читаю this article, объясняя модель памяти C# и утверждает, что в C# все записи являются изменчивыми, но чтение не является. Я задаюсь вопросом, возможно ли, что результаты «CreatePersonLight» будут «кэшированы» в первом потоке, и он не увидит, какой второй поток был произведен.

Кроме того, когда в конце SomeMethod я могу получить доступ к экземпляру экземпляра person (person.Name), не получилось бы получить неправильный результат из-за reordering?

Update 2

Вопрос Making variables captured by a closure volatile определенно связана (именно поэтому он является первым звеном в моей должности), но я не думаю, что это то же самое/дублировать. Кроме того, он предполагает, что:

... казалось бы, что нет никакого способа, чтобы заставить летучую семантику на захваченном локальных переменные ...

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

+0

Тот факт, что вам не нравится ответ на свой вопрос Безразлично Это не дубликат. Другой вопрос задает то же самое. Тот факт, что вы не верите в ответ (несмотря на отсутствие доказательств в поддержку этой позиции), не делает его не дублируемым. – Servy

+0

@Servy, не поймите меня неправильно, мне нравится [этот вопрос] (http://stackoverflow.com/questions/9413080/making-variables-captured-by-a-closure-volatile) и обсуждаемая в нем тема , Моя интерпретация его применительно к моей ситуации заключается в том, что мне нужен надлежащий барьер памяти. Однако я не уверен на 100%, что моя интерпретация верна. –

ответ

0

После нескольких исследований и исследований, я думаю, что могу ответить на свой вопрос.

Я действительно переусердствовал.

В обоих исходном коде и в коде для обновления 1 нет синхронизации необходим вследствие секции 3.10 Выполнения заказа из C# спецификации:

Исполнение C# программных средств, такие, что побочные эффекты каждого исполняемого потока сохраняются в критических точках выполнения. Побочный эффект определяется как чтение или запись изменчивого поля, запись в энергонезависимую переменную, запись на внешний ресурс и металирование исключения. Критические точки выполнения, в которых необходимо сохранить порядок этих побочных эффектов : ссылки на изменчивые поля (§10.5.3), операторы блокировки (§8.12) и создание и прекращение потоков.

Мое понимание спецификации является то, что при Parallel.Invoke завершении я гарантированно увидеть правильные значения в «лицо» и «животное»

Смежные вопросы