Путаница в инструкции lock В C#

Это из MSDN: Ключевое слово Lock гарантирует, что один поток не войдет критическая секция кода, пока другой поток находится в критическая секция.

тут критическая секция надо же критическая секция?

или это значит: Ключевое слово Lock гарантирует, что один поток не войдет любой критический раздел, охраняемый объектом кода, пока другой поток находится в любой критический раздел, охраняемый одним и тем же объектом. ?

    class Program
{
    static void Main(string[] args)
    {
        TestDifferentCriticalSections();

        Console.ReadLine();
    }

    private static void TestDifferentCriticalSections()
    {
        Test lo = new Test();

        Thread t1 = new Thread(() =>
        {
            lo.MethodA();
        });
        t1.Start();

        Thread t2 = new Thread(() =>
        {
            lo.MethodB();
        });
        t2.Start();
    }
}

public class Test
{
    private object obj = new object();

    public Test()
    { }

    public void MethodA()
    {
        lock (obj)
        {
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(500);
                Console.WriteLine("A");
            }
        }
    }

    public void MethodB()
    {
        lock (obj)
        {
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(500);
                Console.WriteLine("B");
            }
        }
    }
}

6 ответов


вопрос запутанно сформулирован, и ответы до сих пор не особенно ясны. Позвольте мне перефразировать вопрос на несколько вопросов:--5-->

(1) гарантирует ли оператор блокировки, что в теле оператора блокировки одновременно находится не более одного потока?

нет. Например:

static readonly object lock1 = new object();
static readonly object lock2 = new object();
static int counter = 0;
static object M()
{
    int c = Interlocked.Increment(ref counter);
    return c % 2 == 0 ? lock1 : lock2;
}

...
lock(M()) { Critical(); }

возможно для 2 потоков оба находиться в теле оператора замка в тоже время, потому что оператор lock блокирует два разных объекта. Поток Альфа может вызвать M() и получить lock1, а затем поток бета может вызвать M () и получить lock2.

(2) предполагая, что мой оператор блокировки всегда блокирует один и тот же объект, гарантирует ли оператор блокировки, что в теле блокировки одновременно находится не более одного "активного" потока?

да. Если у вас есть:

static readonly object lock1 = new object();
...
lock(lock1) { Critical(); }

после этого Альфа потока может принять замок, и бета потока будет блок до тех пор пока замок не будет доступен перед входом тела замка.

(3) предполагая, что у меня есть два оператора блокировки, и оба оператора блокировки каждый раз фиксируются на одном и том же объекте, гарантирует ли оператор блокировки, что в теле любой блокировки одновременно находится не более одного "активного" потока?

да. Если у вас есть:

static readonly object lock1 = new object();
...
static void X() 
{
    lock(lock1) { CriticalX(); }
}
static void Y() 
{
    lock(lock1) { CriticalY(); }
}

потом, если нить Альфа в X и берет замок, и поток бета В Г, затем поток бета будет блок до тех пор пока замок не будет доступен перед входом тела замка.

(4) Почему вы ставите "активный" в "пугающие кавычки"?

обратить внимание на то, что это возможно для ожидание резьбы в теле замка. Вы можете использовать Monitor.Wait метод "приостановить" поток, который находится в теле блокировки, и позволить заблокированному потоку стать активным и ввести это тело блокировки (или другое тело блокировки, которое блокирует то же самое объект.) Ожидающая нить будет оставаться в состоянии" ожидания " до тех пор, пока не будет пульсировать. Через некоторое время после того, как он пульсирует, он присоединяется к" готовой " очереди и блоки пока в замке нет" активной " нити. Затем он возобновляется в том месте, где он остановился.


поставить блокировку на объект. Если другой поток пытается получить доступ к критическому разделу, отмеченному этим объектом одновременно, он блокируется до тех пор, пока блокировка не будет удалена/завершена.

пример:

public static object DatabaseLck= new object();

lock (DatabaseLck) {
        results = db.Query<T>(query).ToList();
     }

или

lock (DatabaseLck) {
       results = db.Query<T>(string.Format(query, args)).ToList();
  }

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


Это один и тот же критический раздел.

lock (synclock)
{
  // the critical section protected by the lock statement
  // Only one thread can access this at any one time
}

посмотреть оператор Lock на MSDN:

ключевое слово lock помечает блок оператора как критический раздел, получая блокировку взаимного исключения для данного объекта, выполняя инструкцию, а затем освобождая блокировку.


или это означает: ключевое слово lock гарантирует, что один поток не вводит критический раздел кода, а другой поток в любом критическом разделе. ?

нет. Это не значит, что. Это означает критическую секцию, защищенную этим замком и только этим замком.


Update, следующий пример кода:

Если вы используете один объект для блокировки, он будет заблокировать все критические разделы, в результате чего другие потоки блокируются до освобождения. В примере кода после блокировки в MethodA был введен, все остальные потоки, идущие замок и замок на MethodB будет блокировать, пока блокировка не будет освобождена (это происходит, потому что вы блокируете один и тот же объект в обоих методах).


Это не значит любой, хотя вы можете защитить 2 блока кода от ввода более чем одним потоком одновременно, заблокировав их с одним и тем же объектом. Это общая парадигма - вы можете заблокировать свою коллекцию как для очистки, так и для записи.


нет это означает, что другой поток не войдет в критический раздел, защищенный этим оператором блокировки.

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

Так перевод : The lock ключевое слово гарантирует, что один поток не входит в раздел кода, защищенный lock в то время как другой поток находится в этом разделе кода (защищен lock )


критическая секция что это говорит о разделе охраняется заявления замком.

любой критический раздел, который блокируется на том же объекте, будет заблокирован от получения доступа.

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