2

In the context of this and this previously asked questions and also considering this answer I am wondering if in the following c# code access to the local captured variables must be synchronized.

// 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
}

The code above may look as though we are accessing local variables, however considering that behind the scenes local variables are captured in closure and access to those captured variables is happening in different threads I have a feeling that a proper memory barrier is missing.

My question is: Does access to person and animal variables need to be synchronized? If yes, is the following a correct way of doing it or am I overthinking this?

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

Update 1

Let me complicate my example a little and explain my thought process.

// 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
}

As far as I understand there are three threads involved in this code. First thread that executes "SomeMethod", second thread that executes "CreatePersonHeavy", and third thread that executes "CreateAnimalHeavy".

I am reading this article explaining c# memory model and it states that in c# all writes are volatile, but reads are not. I am wondering then if it is possible that results of "CreatePersonLight" be "cached" in first thread and it will not see whatever second thread produced.

Additionally when at the end of SomeMethod I access a property of a person instance (person.Name) would it not be possible to still get a wrong result due to reordering?

Update 2

The question Making variables captured by a closure volatile is certainly related (that's why it is the first link in my original post) but I don't think is the same/duplicate. Besides it suggests that:

...it would appear that there is no way to force volatile semantics onto captured local variables...

which I am not sure is true. That said it does not still answer my question directly whether in the presented here code access to captured variables must be synchronized or not.

Community
  • 1
  • 1
Nick Y
  • 172
  • 1
  • 5
  • The fact that you don't like the answer to your question doesn't make it not a duplicate. The other question is asking the exact same thing. The fact that you don't believe the answer (despite having no evidence to support that position) doesn't make it not a duplicate. – Servy Mar 15 '16 at 02:04
  • @Servy, don't get me wrong, I do like [this question](http://stackoverflow.com/questions/9413080/making-variables-captured-by-a-closure-volatile) and the topic it discusses. My interpretation of it applied to my situation is that I do need a proper memory barrier. However I am not 100% sure that my interpretation is correct. – Nick Y Mar 17 '16 at 18:02

1 Answers1

0

After some more reading and research I think I can answer my own question.

I was indeed overthinking it.

In both original code and in the code for Update 1 no synchronization is necessary due to section 3.10 Execution Order of the C# specs:

Execution of a C# program proceeds such that the side effects of each executing thread are preserved at critical execution points. A side effect is defined as a read or write of a volatile field, a write to a non-volatile variable, a write to an external resource, and the throwing of an exception. The critical execution points at which the order of these side effects must be preserved are references to volatile fields (§10.5.3), lock statements (§8.12), and thread creation and termination.

My understanding of the spec is that upon Parallel.Invoke completion I am guaranteed to see proper values in "person" and "animal"

Nick Y
  • 172
  • 1
  • 5