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

发布于 2024-07-29 10:57:21 字数 840 浏览 6 评论 0原文

我有一个代码如下的类

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

宛菡 2024-08-05 10:57:21

C# 中的lock(以及通常在 .NET 中扩展为的Monitor)是一个内存屏障 - 具体来说,是获取时的读屏障,释放时的写屏障。 至于易失性,它为每个对该字段的读取和写入添加了屏障。 所以,是的,您应该安全地使用易失性(假设您没有显示的其余代码正在正确执行所有操作)。

lock in C# (and, in general, the Monitor that it expands to in .NET) is a memory barrier - specifically, read barrier on acquire, write barrier on release. As for volatile, it adds a barrier for every read and write to the field. So, yes, you should be safe with volatile (assuming the rest of your code, which you didn't show, is doing everything correctly).

自在安然 2024-08-05 10:57:21

如果没有 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.

话少心凉 2024-08-05 10:57:21

如果我记得,性能不是很好,但您可以使用 ReaderWriterLock 实现 1 个写入器和多个读取器。

If I recall, the performance is not great, but you could use a ReaderWriterLock to implement 1 writer and multiple readers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文