her*_*son 1 c# multithreading volatile
更新:现在使用基于以下评论的只读集合
我相信下面的代码应该是线程安全的"锁定免费"代码,但是要确保我没有遗漏某些东西......
public class ViewModel : INotifyPropertyChanged
{
//INotifyPropertyChanged and other boring stuff goes here...
private volatile List<string> _data;
public IEnumerable<string> Data
{
get { return _data; }
}
//this function is called on a timer and runs on a background thread
private void RefreshData()
{
List<string> newData = ACallToAService();
_data = newData.AsReadOnly();
OnPropertyChanged("Data"); // yes, this dispatches the to UI thread
}
}
Run Code Online (Sandbox Code Playgroud)
具体来说,我知道我可以使用一个lock(_lock)甚至是一个Interlocked.Exchange()但我不相信在这种情况下需要它.volatile关键字应该足够(以确保不缓存该值),不是吗?有人可以确认一下,或者让我知道我对线程的理解不清楚:)
我不知道这是否"安全"; 它取决于你所说的"安全".例如,如果将"安全"定义为"保证从所有线程中观察到所有易失写入的一致排序",则不保证您的程序在所有硬件上都是"安全的".
这里最好的做法是使用锁,除非你有充分的理由不这样做.写这个有风险的代码你有什么理由?
更新:我的观点是,低锁或无锁代码风险极高,世界上只有少数人真正了解它.让我举一个例子,来自Joe Duffy:
// deeply broken, do not use!
class Singleton {
private static object slock = new object();
private static Singleton instance;
private static bool initialized;
private Singleton() {}
public Instance {
get {
if (!initialized) {
lock (slock) {
if (!initialized) {
instance = new Singleton();
initialized = true;
}
}
}
return instance;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码坏了; 正确实现C#编译器为您编写一个为该实例返回null的程序是完全合法的.你能看到怎么样?如果没有,那么你没有做低锁或无锁编程的业务; 你会弄错的.
我自己也弄不清楚这些东西; 它打破了我的大脑.这就是为什么我试图永远不做低锁编程,这种编程与专家分析的标准实践完全不同.
这取决于意图是什么.列表的get/set是原子的(即使没有volatile)和非缓存的(volatile),但是调用者可以改变列表,这不保证是线程安全的.
还有一种竞争条件可能会丢失数据:
obj.Data.Add(value);
Run Code Online (Sandbox Code Playgroud)
这里的价值很容易被抛弃.
我会使用一个不可变(只读)集合.