何时在线程安全锁定代码中使用’volatile’或’Thread.MemoryBarrier()’? (C#)
我什么时候应该使用volatile / Thread.MemoryBarrier()来保证线程安全?
如果要跨线程访问变量而不锁定,则使用volatile
/ Thread.MemoryBarrier()
。
primefaces变量(例如int
总是一次读写整个变量。 这意味着在另一个线程更改之前,您将永远不会获得一半的值,而在更改之后,另一半则不会。 因此,您可以安全地在不同的线程中读取和写入值,而无需同步。
但是,编译器可能会优化掉一些读取和写入,而使用volatile
关键字会阻止这些读取和写入。 例如,如果您有一个这样的循环:
sum = 0; foreach (int value in list) { sum += value; }
编译器实际上可以在处理器寄存器中进行计算,并且仅在循环之后将值写入sum
变量。 如果将sum
变量设置为volatile
,则编译器将生成用于为每个更改读取和写入变量的代码,以使其在整个循环中的值是最新的。
怎么了?
private static readonly object syncObj = new object(); private static int counter; public static int NextValue() { lock (syncObj) { return counter++; } }
?
这会为您完成所有必要的锁定,内存障碍等。 与基于volatile
和Thread.MemoryBarrier()
任何自定义同步代码相比,它的理解和可读性更强。
编辑
我想不出我使用volatile
或Thread.MemoryBarrier()
的场景。 例如
private static volatile int counter; public static int NextValue() { return counter++; }
不等同于上面的代码,并且不是线程安全的( volatile
不会使++
神奇地成为线程安全的)。
在这种情况下:
private static volatile bool done; void Thread1() { while (!done) { // do work } } void Thread2() { // do work done = true; }
(应该工作)我会使用ManualResetEvent来表示Thread2何时完成。
基本上,如果您使用任何其他类型的同步来使您的代码线程安全,那么您不需要。
大多数锁定机制(包括锁定)自动暗示内存屏障,以便多个处理器可以获得正确的信息。
Volatile和MemoryBarrier主要用于无锁情况,您试图避免锁定的性能损失。
编辑:你应该阅读Joe Duffy关于CLR 2.0内存模型的这篇文章 ,它澄清了很多东西(如果你真的很感兴趣,你应该阅读来自Joe Duffie的所有文章,他是大多数并行的专家。 。净)
顾名思义,保证将缓存值刷新到内存,以便所有线程都看到相同的值。 例如,如果我有一个整数,其最新写入保存在缓存中,其他线程可能看不到。 他们甚至可以看到他们的整数缓存副本。 将变量标记为volatile会使其直接从内存中读取。
Sriwantha Sri Aravinda Attanayake
上述就是C#学习教程:何时在线程安全锁定代码中使用’volatile’或’Thread.MemoryBarrier()’? (C#)分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/960040.html