我想了解如何编写线程安全代码。
例如我的游戏中有这段代码:
bool _done = false;
Thread _thread;
// main game update loop
Update()
{
// if computation done handle it then start again
if(_done)
{
// .. handle it ...
_done = false;
_thread = new Thread(Work);
_thread.Start();
}
}
void Work()
{
// ... massive computation
_done = true;
}
如果我理解正确,主游戏线程和我的 _thread
可能有自己的 _done
缓存版本,并且一个线程可能永远看不到 _done
在另一个线程中更改了吗?
如果可以,如何解决?
是否可以通过仅应用
volatile
关键字来解决。或者是否可以通过
Interlocked
的方法如Exchange
和Read
来读取和写入值?如果我用
lock (_someObject)
包围_done
读写操作,我需要使用Interlocked
或其他东西来防止缓存?
编辑 1
- 如果我将
_done
定义为volatile
并从多个线程调用Update
方法。在我将_done
分配给 false 之前,是否有可能有 2 个线程将进入if
语句?
最佳答案
是的,但从技术上讲,这不是
volatile
关键字的作用;不过,它有一个副作用——volatile
的大多数用途都是为了那个副作用;实际上volatile
的 MSDN 文档现在只列出了这种副作用情况 (link) - 我猜想 actual original 措辞(关于重新排序指令)太困惑了?所以也许这现在是官方用法?Interlocked
没有bool
方法;您需要使用int
和0
/1
之类的值,但这几乎就是bool
无论如何 - 请注意Thread.VolatileRead
也可以工作lock
有一个完整的栅栏;你在那里不需要任何额外的构造,lock
本身就足以让 JIT 理解你需要什么
就个人而言,我会使用volatile
。您已经方便地以递增的间接费用顺序列出了您的 1/2/3。 volatile
将是这里最便宜的选择。
关于c# - 如何为 Unity3D 编写线程安全的 C# 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43274759/