Effects of "lock (obj) {/ * empty * /}" on thread visibility

Given the code:

object sync = new object();
string result = null;

var thread = new Thread(() => {
   var workResult = DoSomeWork();
   lock (sync) { result = workResult; }
});

thread.Start();
thread.Join();

lock (sync) {
   // No code in here - not 'atomic' wrt the thread
   // as the thread has been terminated and joined.
}

// Is it SAFE to access the `result` here?
UseResultFromThread(result);

      

Does empty provide a lock

random event before the visibility of the stream of the value result

set inside the stream?

If not (and even if it is), is there a better approach than using it lock

here, given the previously established order of life of threads?

Or (and question Y) is it Join

sufficient for flow visibility of the modified variable (s)?

+3


source to share


1 answer


Will work, yes, since the lock input is associated with a memory barrier. Instead, you can use Thread.MemoryBarrier

to just do it. The performance will be almost the same, it will be mainly to improve the semantics for the reader.

However, things get much easier if you use tasks instead, as they are specifically designed to represent operations that have a result, and they will keep track of the appropriate timing when that result is accessed. Your code can be written simply:

var result = Task.Run(() => DoSomeWork()).Result;
UseResultFromThread(result);

      



Of course, there is no point in creating a new thread to do some work if you just wait for it to complete. At this point, you could just use the original thread to do the work and not bother the second thread in the first place; which greatly simplifies the whole thing:

UseResultFromThread(DoSomeWOrk());

      

And done.

+5


source







All Articles