如果我在写入变量时锁定,如果读取是原子的,那么在读取时是否也需要锁定?
我有一个代码如下的类
private readonly object m_lock = new object();
private IClient m_client
private object m_context;
当设置客户端和上下文时,我锁定如下
lock(m_lock)
{
m_client = theClientFromSomewhere;
m_context = contextObject;
}
我的问题是,如果我只需要自己获取 m_client
,这样做安全吗?
var localClient = m_client;
Debug.Assert(localClient != null);
localClient.DoStuff();
m_client
是一个引用类型,因此读取(当分配给 localClient
时)保证是原子的,因此这应该可以在单个 CPU 上正常工作。
我可以(理论上也是)使 m_client
变量 易失性
,然后通过防止其他 CPU 的乱序读取,这在多个 cpu 上是安全的,但是问题是,写入时锁定是否可以安全地读取而不不稳定?
写入时锁定是否会“刷新”CPU 缓存,以便读取时不会出现乱序?
I have a class with code as follows
private readonly object m_lock = new object();
private IClient m_client
private object m_context;
When setting the client and context, I lock as follows
lock(m_lock)
{
m_client = theClientFromSomewhere;
m_context = contextObject;
}
My question is, if I only need to get the m_client
by itself, is it safe to do this?
var localClient = m_client;
Debug.Assert(localClient != null);
localClient.DoStuff();
m_client
is a reference type, so the read (when assigning to localClient
) is guaranteed to be atomic, so this should work fine on a single CPU.
I could (also in theory) make the m_client
variable volatile
, and then this would be safe across multiple cpu's by preventing out-of-order reads by other CPU's, but the question is, does the lock-when-writing make it safe to read without being volatile?
Does locking when writing "flush" the CPU caches so that when they do a read it won't be out-of-order?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
C# 中的
lock
(以及通常在 .NET 中扩展为的Monitor
)是一个内存屏障 - 具体来说,是获取时的读屏障,释放时的写屏障。 至于易失性
,它为每个对该字段的读取和写入添加了屏障。 所以,是的,您应该安全地使用易失性
(假设您没有显示的其余代码正在正确执行所有操作)。lock
in C# (and, in general, theMonitor
that it expands to in .NET) is a memory barrier - specifically, read barrier on acquire, write barrier on release. As forvolatile
, it adds a barrier for every read and write to the field. So, yes, you should be safe withvolatile
(assuming the rest of your code, which you didn't show, is doing everything correctly).如果没有 m_context,则不需要锁,因为读取和写入都是原子的。 但是,如果当您读取 m_client 时也使用 m_context,那么您必须锁定两者,以防止在更新 m_client 之后但更新 m_context 之前发生上下文切换的情况。
If you didn't have m_context, you wouldn't need the lock as both the read and the write are atomic. If, however, when you read m_client you also use m_context, then you have to lock both to prevent a situation where there's a context switch after updating m_client but before updating m_context.
如果我记得,性能不是很好,但您可以使用 ReaderWriterLock 实现 1 个写入器和多个读取器。
If I recall, the performance is not great, but you could use a ReaderWriterLock to implement 1 writer and multiple readers.