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)?
source to share
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.
source to share