如果我在写入变量时锁定,在读取时是否还需要锁定,如果读取是原子的?

时间:2009-07-23 04:09:25

标签: c# multithreading locking volatile

我有一个代码如下的课程

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是一种引用类型,因此读取时(分配给localClientis guaranteed to be atomic时,这应该可以在单个CPU上正常工作。

我可以(也在理论上)制作m_client变量volatile,然后通过防止其他CPU的无序读取在多个cpu中安全,但问题是,锁定时写入是否可以安全地读取而不会发生变化?

在写入“刷新”CPU缓存时是否锁定,以便在读取时不会出现乱序?

3 个答案:

答案 0 :(得分:3)

C#中的{p> lock(通常,它在.NET中扩展到的Monitor)是一个内存屏障 - 特别是读取时的屏障,发布时的写屏障。对于volatile,它为每次读取和写入字段添加了障碍。所以,是的,您应该对volatile保持安全(假设您未显示的其余代码正在正确执行所有操作)。

答案 1 :(得分:0)

如果你没有m_context,你就不需要锁,因为read和write都是原子的。但是,如果读取m_client时也使用m_context,则必须同时锁定两者以防止在更新m_client之后但在更新m_context之前存在上下文切换的情况。

答案 2 :(得分:0)

如果我记得,性能不是很好,但您可以使用ReaderWriterLock来实现1位作家和多位读者。