public class Service
{
private List<SomeType> _list = null;
public static List<SomeType> GetSomeTypeList()
{
if (_list != null) return _list;
List<SomeType> _temp = null;
_temp = FunctionToGetSomeTypeValue();
_list = _temp;
return _list;
}
}
是服务端代码,GetSomeTypeList可能被多个请求(线程)调用,FunctionToGetSomeTypeValue即使在不同的线程中返回的结果也是一样的,是静态资源, 但 FunctionToGetSomeTypeValue 可能因返回 null 而失败。 我的意图是在需要时获取资源,并在每次调用时尝试获取它,除非它是成功的。 问题是在更新 _list 时,_list = _temp,我是否需要使用 lock(lockobj) {_list=_temp} 进行锁定?
如果两个线程都在调用GetSomeTypeList(),并且都去调用FunctionToGetSomeTypeValue(),一个成功,一个失败,成功一个调用 _list=_temp 首先,失败的一个然后分配 _list=null。我对这种情况没意见,因为最终 _list 将处于良好状态,并且所有调用都只返回 _list。
我不明白的是,如果我不使用锁,是否有可能为 _list 对象分配不正确的值(意外值)?不为空,也不正确的 _temp 和正确的地址。
所以实际的问题是,假设有变量:static int Obj = 0;
- 一个线程正在设置
Obj = 1; - 另一个线程正在设置
Obj = 2;
如果 Obj 的设置没有锁定,Obj 的值应该是 1 或 2,不会是其他任何东西,对吗? 如果 Obj 是一个 struct 怎么办?
引用对象(地址)的赋值是原子操作吗? 简单类型 object(int, struct) 呢?
请您参考如下方法:
除了其他答案之外,还有一个框架类,Lazy<T> ,这允许以线程安全的方式对对象进行惰性实例化。无需自己编写:
public class Service
{
private static Lazy<List<SomeType>> _list = new Lazy<List<SomeType>>(
()=>FunctionToGetSomeTypeValue(),
isThreadSafe: true
);
public static List<SomeType> GetSomeTypeList()
{
return _list.Value;
}
}
