lock(objlocker) 是不是使该对象在应用程序范围内线程安全?静态成员是不是自动线程安全?

Posted

技术标签:

【中文标题】lock(objlocker) 是不是使该对象在应用程序范围内线程安全?静态成员是不是自动线程安全?【英文标题】:Does the lock(objlocker) make that object thread safe app wide? And are static members automatically thread safe?lock(objlocker) 是否使该对象在应用程序范围内线程安全?静态成员是否自动线程安全? 【发布时间】:2010-09-21 10:06:02 【问题描述】:

当您锁定一个对象时,该对象是否会在整个应用程序中被锁定?

例如,简而言之,第 19.6.1 节“线程安全和 .NET 框架类型”中来自 C# 3.0 的这个 sn-p:

static void AddItems(  )
  
    for (int i = 0; i < 100; i++)
      lock (list)
        list.Add ("Item " + list.Count);

    string[] items;
    lock (list) items = list.ToArray(  );
    foreach (string s in items) Console.WriteLine (s);
  

是否第一次锁定:

lock (list)
        list.Add ("Item " + list.Count);

阻止另一个线程访问:

lock (list) items = list.ToArray(  );

还是可以同时执行?

CLR 是否会自动使您的静态方法线程安全?还是由开发者决定?

谢谢, 约翰

【问题讨论】:

【参考方案1】:

另外需要注意的是静态构造函数是由运行时以线程安全的方式执行的。如果您正在创建一个单例并将其声明为:

public class Foo

    private static Foo instance = new Foo();

    public static Foo Instance
    
        get  return instance; 
    

那么它将是线程安全的。但是,如果您在 Instance getter 内部实例化一个新的 Foo,那么您需要编写自己的线程安全(即锁定对象)

【讨论】:

【参考方案2】:
class UsefulStuff 
    object _TheLock = new object  ;
    public void UsefulThingNumberOne() 
        lock(_TheLock) 
            //CodeBlockA
        
    
    public void UsefulThingNumberTwo() 
        lock(_TheLock) 
            //CodeBlockB
        
    

CodeBlockACodeBlockB 被阻止在不同的线程中同时执行,因为它们都被锁定在同一个对象实例_TheLock 上。

_TheLock 本身的方法完全不受影响。

【讨论】:

【参考方案3】:

CLR 不会自动使静态方法成为线程安全的;你必须自己做。

lock(list) 将该对象用作锁,因此如果不同的线程使用 lock(list) 到达另一个点(具有相同的“列表”对象),则另一个线程将阻塞,直到第一个线程释放锁。

需要明确的是,lock(foo) 不会“锁定 foo 对象”,而是获取与 foo 对象关联的锁,以便临界区(构造“lock(o) stmt”中的语句)仅在当前线程获得锁时运行。

【讨论】:

以上是关于lock(objlocker) 是不是使该对象在应用程序范围内线程安全?静态成员是不是自动线程安全?的主要内容,如果未能解决你的问题,请参考以下文章

UnityC#的lock用法简记

[转]C# 理解lock

std::condition_variable 是不是真的在阻塞之前解锁了给定的 unique_lock 对象?

lock() 是不是保证按请求的顺序获得?

这是不是有太多依赖项无法通过构造函数注入到对象中?

c# lock static对象, 跪求高手。