1

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

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

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 会自动使您的静态方法线程安全吗?还是这取决于开发商?

谢谢,约翰

4

3 回答 3

5

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

public class Foo
{
    private static Foo instance = new Foo();

    public static Foo Instance
    {
        get { return instance; }
    }
}

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

于 2008-11-08T09:42:25.070 回答
3

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

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

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

于 2008-11-08T04:13:55.547 回答
3
class UsefulStuff {
    object _TheLock = new object { };
    public void UsefulThingNumberOne() {
        lock(_TheLock) {
            //CodeBlockA
        }
    }
    public void UsefulThingNumberTwo() {
        lock(_TheLock) {
            //CodeBlockB
        }
    }
}

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

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

于 2008-11-08T04:19:20.807 回答