当涉及高速网络消息传递时,使用易失性字典是一个不错的选择吗?

Tob*_*byB 1 c# networking volatile thread-safety

前提

我正在开发一个多人游戏,我有许多网络控制的演员,我决定将女巫的输入存储在一个易变的字典中:

public static volatile Dictionary<string, QuickMessage> quickPlayerMessages;
Run Code Online (Sandbox Code Playgroud)

并且每一帧演员都从该字典中获取他们的值,但与此无关,我还有一个接收器线程不断更新该字典,因此值会不断更改,并且键可能会被删除或添加到其中。我做了一些测试,这有效,但是......

我的顾虑

我不完全理解 volatile 修饰符,我知道它应该消除一些可能导致读取部分写入信息的优化。我还听说这并不像使用锁定机制那样真正起作用。虽然我确实选择了这个解决方案,因为它为我减少了很多复杂性,而且看起来它的响应速度相当快(速度方面),但我确实对此感到不安。

是否有任何可能出现的问题或我应该从这种方法中意识到的问题?

Jon*_*asH 5

volatile可能不是正确的方法。volatile 的作用是强制从内存而不是缓存中读取值。读取或写入引用或小于 IntPtr 的值在 c# 中是原子的。但是如果没有某种内存屏障,该值可以被缓存,并且一个线程上的更改可能对其他线程不可见。Volatile 插入了一些内存屏障来解决一些可见性问题。

在这种情况下,您似乎没有替换字典,因此volatile什么也不做。但是,您提到您正在更新字典。这不是没有锁的线程安全。但是您可能会考虑使用 aConcurrentDictionary<TKey, TValue>代替。然而,并发字典只能保证字典本身是线程安全的,您仍然需要考虑程序的整体线程安全性。

此外,您主要关心的应该是程序是否正确,速度是次要的。

  • @托比B 没有。易失性不是一个神奇的线程安全关键字。它解决了一个特定的、非常狭窄的问题。即使这样,使用 Interlocked.Exchange/Read 可能会更好。如果有疑问,您应该使用*锁*。锁有其自身的问题和危险,但它解决了许多可能的并发问题。编写多线程代码不是使用反复试验的地方,它是轻松编写 0.001% 的时间失败并且无法调试的代码的方法。您需要对危险有一定的了解。 (4认同)