Skip to main content
 首页 » 编程设计

c#之在不同线程中为静态变量分配相同的值,仍然需要锁定

2024年05月10日38over140

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; 
   } 
}