如果我在锁定期间修改引用字段,是否需要保持易失性?
考虑以下代码,该代码发生在后台线程(“线程 B”)中:
List<T> invocationQueueCopy;
lock (invocationQueue)
{
invocationQueueCopy = invocationQueue;
invocationQueue = new List<T>();
}
在另一个线程(“线程 A”)中,我只需在添加“invokingQueue”之前锁定它:
lock (invocationQueue)
{
invocationQueue.Add(args);
}
我已经读到引用分配是原子的,但可以是否会发生“线程 A”在收到锁后最终写入旧列表(“线程 B”中替换的列表)?我读过其他答案,暗示它可以,如果引用的值存储在“线程 A”上的寄存器中,那么它不会知道“线程 B”已修改类中的值。如果是这样,声明“incallingQueue”易失性会阻止这种情况发生吗?
注意:
- 我知道我可以克隆然后清除列表。
- 我 知道我可以有一把单独的锁 列表的对象。
但除非有必要,否则我宁愿不做这两件事。
提前致谢。
编辑:
只是从 Adam 的评论中澄清:invocationQueue 是一个私有字段,它是在此类内部创建的,并且从未暴露给外界,因此除了这两个方法之外,没有任何东西可以锁定它。
Consider the following code, which takes place in a background thread ("thread B"):
List<T> invocationQueueCopy;
lock (invocationQueue)
{
invocationQueueCopy = invocationQueue;
invocationQueue = new List<T>();
}
In another thread ("thread A") I simply lock "invocationQueue" before adding to it:
lock (invocationQueue)
{
invocationQueue.Add(args);
}
I have read that reference assignment is atomic, but could it ever occur that "thread A" will end up writing to the old list (the one replaced in "thread B") after receiving the lock? I have read other answers that imply it could, if the value of the reference were stored in a register on "thread A" then it would not know that "thread B" had modified the value in the class. If this is so, would declaring "invocationQueue" volatile prevent this?
Notes:
- I know I could clone then clear the list.
- I
know I could have a separate lock
object for the list.
But I'd rather not do either of these things unless it is required.
Thanks in advance.
Edit:
Just to clarify from Adam's comments: invocationQueue is a private field which is created internally to this class and never exposed to the outside world so nothing could lock on it except these two methods.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
编辑:您的解决方案将会起作用。锁定会创建一个 完整栅栏,因此任何缓存都会被阻止,基本上意味着您将始终获取列表引用的最新值。正如评论中所建议的,唯一的事情是您应该对中立对象进行锁定,而不是列表本身。
以下是错误的!!但我还是把它放在这里是为了展示硬线程可能是多么的操蛋……事实上,下面的推理被锁创建了一个完整的栅栏这一事实所击败。
EDIT: Your solution will work. Lock creates a full fence so any caching is prevented, basically meaning you'll always get the most recent value for the list reference. The only thing, as suggested in the comments is the fact that you should do the locking on a neutral object, not the list itself.
The following is wrong!! But I let it here anyway to show how fu*** hard threading might be... the fact is the following reasoning is defeated by the fact that lock creates a full fence.