c# - 我可以避免对很少更改的变量使用锁吗?

标签 c# multithreading concurrency volatile

我一直在阅读 Joe Duffy 关于并发编程的书。我有一个关于无锁线程的学术问题。

首先:我知道无锁线程充满了危险(如果你不相信我,请阅读书中关于内存模型的部分)

不过,我有一个问题: 假设我有一个带有 int 属性的类。

这个属性引用的值会被多个线程非常频繁地读取

值发生变化的情况极为罕见,当发生变化时,将由单个线程进行更改。

如果它确实发生了变化,而另一个使用它的操作正在运行中,没有人会失去一根手指(任何人使用它所做的第一件事就是将它复制到局部变量)

我可以使用锁(或 readerwriterlockslim 来保持读取并发)。 我可以将变量标记为 volatile(很多例子都是这样做的)

但是,即使是 volatile 也会对性能造成影响。

如果我在 VolatileWrite 发生变化时使用它,并保持读取访问正常,会怎样?像这样:

public class MyClass
{
  private int _TheProperty;
  internal int TheProperty
  {
    get { return _TheProperty; }
    set { System.Threading.Thread.VolatileWrite(ref _TheProperty, value); }
  }
}

我不认为我会在现实生活中尝试这个,但我很好奇答案(最重要的是,作为我是否理解我一直在阅读的内存模型内容的检查点)。

最佳答案

将变量标记为“volatile”有两个作用。

1) 读写具有acquire和release语义,因此其他内存位置的读写不会相对于该内存位置的读写“时间上前后移动”。 (这是一个简化,但你明白我的意思。)

2) 抖动产生的代码不会“缓存”一个看似逻辑上不变的值。

前一点是否与您的场景相关,我不知道;您只描述了一个内存位置。仅具有 volatile 写入而没有 volatile 读取是否重要由您决定。

但在我看来,后一点非常相关。如果您在非 volatile 变量上有自旋锁:

while(this.prop == 0) {}

抖动有权生成这段代码,就像你写的一样

if (this.prop == 0) { while (true) {} }

它是否真的这样做了,我不知道,但它有权这样做。如果您想要代码在每次循环时实际重新检查属性,将其标记为易变是正确的方法。

关于c# - 我可以避免对很少更改的变量使用锁吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2158001/

相关文章:

c# - xamarin 中的 float 菜单栏

c# - Nlog 从 Appsettings 获取 Azure Blob 存储连接字符串

multithreading - Delphi 中 CPU 使用率 100%

java - 通用的无锁同步

algorithm - 强连通分量 (SCC) 的并发算法

c# - 如何使用 C# 和 Office Interop 获取 Office 文档的完整文件名?

c# - 使用 System.Drawing 勾勒文本?

c# - 这个 StaticRandom 类是线程安全的吗?

c++ - 对包含整数的文本文件进行排序,必须逐行进行排序

scala - 如何在 RxScala/Java 中使用多线程执行 map、filter、flatMap?