C#多线程:获取必要的读锁定?

And*_*sch 43 c# multithreading

在从多个线程读取变量之前,是否有必要获取锁定?

R. *_*des 94

简短的回答是:这取决于.

答案很长的答案是:

  • 如果它不是共享值,即只有一个线程可以看到它(或使用它),则不需要任何同步.

  • 如果它是一个不可变的值,即你只设置一次然后只读它,那么在没有同步的情况下这样做是安全的(只要你在第一次写入完成之前没有开始读取).

  • 如果这是一个"原始"类型最多32位(例如byte,short,int)你可以得到陈旧(旧)数据读取时.如果那不打扰你,你就定了.如果不希望使用陈旧数据,那么使变量volatile可以解决此问题而无需额外的读取同步.但如果你有赛车作家,你需要遵循以下建议long.

  • 如果这是一个"原始"类型比32位长(例如long,decimal,double)你需要同步的,否则你一个值,另一个"半"读"半壁江山",并获得疯狂的结果.为此,推荐的方法是使用Interlocked类中的方法进行读写操作.

  • 如果它是引用类型,则需要同步以避免看到无效状态(Jeff Lamb的图片示例很好).该lock声明可能足够了点.同样,您需要锁定读取和写入.

还有一些其他要点(例如,锁定多长时间),但我认为这些都足以回答您的问题.

  • 对于在64位模式下运行的应用程序,您是否仍能获得一个值的"一半",另一个值的"一半"? (2认同)

Ken*_*art 11

这取决于变量的类型和您的平台.例如,读取Int64s并不保证在32位计算机上是原子的.因此,Interlocked.Read.


Jef*_*amb 5

如果在1个汇编指令中完成值的加载,则不需要锁定.您不关心10分钟前或1微秒前的值是否发生了变化.你现在只想要价值.

但是,如果你正在加载一个巨大的阵列或图片或什么东西,锁定它可能是个好主意.理论上,您可以在加载数据时获得抢占,并且第一项的一半和第二项的一半.

但是,如果它是一个简单的变量,就像bool或int一样,它没有必要.


Gle*_*enn 5

除了下面的答案,您还可以使用ReadWriterLockSlim执行读锁定.

这将允许您在读取时仅执行读锁定,并在修改变量时执行写入锁定.多个线程可以同时具有读锁定,但是一旦线程请求写锁定,所有新请求都将被阻止,直到它完成为止.

如果您正在进行大量读取而不是多次写入,那么这种锁定将非常有用.

与大多数多线程问题一样,研究它是否足以理解它是否真的适合您的问题,ReadWriterLock不适合每个锁定情况.