Делает ли блокировка (objlocker) этот объект безопасным для всех приложений? И статические члены автоматически потокобезопасны? - PullRequest
1 голос
/ 08 ноября 2008

Когда вы блокируете объект, блокируется ли этот объект во всем приложении?

Например, этот фрагмент из C # 3.0 в разделе Nutshell 19.6.1 «Типы безопасности потоков и .NET Framework»:

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 автоматически делает ваши статические методы потокобезопасными? Или это до разработчика?

Спасибо, John

Ответы [ 3 ]

5 голосов
/ 08 ноября 2008

Еще одна вещь, на которую следует обратить внимание, это то, что статические конструкторы выполняются потокобезопасным способом во время выполнения. Если вы создаете синглтон и объявляете его как:

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

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

Тогда это будет потокобезопасно. Однако, если вы создаете новый Foo внутри получателя Экземпляра, то вам необходимо написать собственную безопасность потока (т. Е. Заблокировать объект)

3 голосов
/ 08 ноября 2008
class UsefulStuff {
    object _TheLock = new object { };
    public void UsefulThingNumberOne() {
        lock(_TheLock) {
            //CodeBlockA
        }
    }
    public void UsefulThingNumberTwo() {
        lock(_TheLock) {
            //CodeBlockB
        }
    }
}

CodeBlockA и CodeBlockB не могут выполняться одновременно в разных потоках, так как они оба заблокированы на одном экземпляре объекта _TheLock.

Методы на _TheLock совершенно не затрагиваются.

3 голосов
/ 08 ноября 2008

CLR автоматически не делает статические методы поточно-ориентированными; ты должен сделать это сам.

блокировка (список) использует этот объект в качестве блокировки, поэтому, если другой поток достигает другой точки с блокировкой (списком) (с тем же объектом «список»), другой поток блокируется до тех пор, пока первый поток не снимет блокировку.

Чтобы было ясно, lock (foo) не "блокирует объект foo", скорее он получает блокировку, связанную с объектом foo, так что критическая секция (оператор в конструкции "lock (o) stmt") работает только тогда, когда текущий поток получил блокировку.

...