我的多线程应用程序使用了大量读取值。这些值是配置值,仅在操作员编辑配置文件时指示应用程序重新加载配置文件而不停机时才会更改。可以从多个线程访问这些值。没有任何线程改变该值。只有在重新加载配置文件时才会发生变异。
由于值可以更改,因此访问它们需要某种形式的同步。但由于它们变化很少,我不想使用互斥锁:
我可以降低级别并直接使用原子操作。例如,我可以使用最新版本的原子指针使Config对象不可变:
然而,原子操作本身也不是免费的。我很难找到他们确实施加什么样的开销的信息(CPU管道停顿?CPU内核之间的某种通信开销?他们是否限制了并发性?不确定。)但我觉得它更好尽可能避免使用它们。
所以我想到了在有限的时间内缓存配置指针,例如持续1秒无需同步即可访问缓存的指针。但是这假设时间查找比原子指针操作更便宜并且对并发性的影响更小。这是真的吗?
所以我的主要问题是:
我的次要问题(为了更好地理解问题)是:
有关我的环境和用例的其他信息:
答案 0 :(得分:1)
我会给出一个部分答案:
所有低级语言都可以通过廉价和原子方式从内存中加载一个值。这不需要在x86上进行互锁访问。实际上,在x86上它只是一个常规的加载指令。我们需要做的就是阻止编译器和运行时(如果有的话)重新排序这个内存访问。这是一个编译障碍。
在C#中,这个工具通过Volatile
类浮出水面。在C ++中,现在有atomic
。我不确定需要什么样的一致性级别。它可能是一个获取负载(在x86上很便宜)。 MSVC还将这些语义应用于volatile
个变量。我不知道其他编译器。 C标准肯定会不为volatile指定这些语义,但有些编译器会这样做。
这个设施很便宜,我认为你可以停止寻找其他任何东西。此操作几乎总是命中共享的CPU缓存行(除非在创建存储之后)。
有关详细信息,请参阅Herb Sutters视频系列“Atomic Weapons”。坦率地说,他也是比我更可靠的来源。