lock(obj) {/* empty */}"关于线程可见性

本文关键字:于线程 线程 可见性 obj empty lock quot | 更新日期: 2023-09-27 17:53:37

给定代码:

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);

lock是否确保在线程内设置的result值的线程可见性之前发生?

如果不是(即使是这样),是否有比使用lock更好的方法在这里给出先前建立的线程生命周期顺序?

或者(和Y问题)Join是否足以实现修改变量的线程可见性?

lock(obj) {/* empty */}"关于线程可见性

它可以工作,是的,因为进入锁涉及内存屏障。您可以使用Thread.MemoryBarrier来代替,只需即可完成此操作。性能将几乎相同,这将主要是为了提高读者的语义。

也就是说,如果您使用任务来代替,整个事情会变得容易得多,因为它们是专门设计来表示具有结果的操作的,并且它们将在访问该结果时负责适当的同步。您的代码可以简单地写成:

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

当然,如果你只是想等待它完成,那么创建一个新线程来做一些工作就没有多大意义了。在这一点上,你可能只是让原来的线程做工作,而不是在第一时间为第二个线程烦恼;这大大简化了整个过程:

UseResultFromThread(DoSomeWOrk());