2009-08-11 2 views
9

У меня есть следующий код:Насколько глубоко заходит замок?

  locker = new object(); 
     lock (locker) 
     { 
      for (int i = 0; i < 3; i++) 
       ver_store[i] = atomic_Poll(power);     
     } 

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

ответ

11

заявления замка не «кода блокировки» или любой ресурс, который идет между фигурными скобками заранее себе.

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

Учитывая Ваш пример кода

10 locker = new object(); 
11 lock (locker) 
12 { 
    ... 
15 } 

Когда нить X достигает 10-й строки создается новый объект и в строке 11 замок приобретается на объекте. Thread X продолжает выполнять любой код внутри блока.

Теперь, когда поток X находится посередине нашего блока, нить Y достигает линии 10. Lo и вот, создается новый объект, и поскольку он создан нитью Y, на данный объект не происходит блокировки. Поэтому, когда поток Y достигает 11, он успешно получит блокировку объекта и продолжит выполнение блока одновременно с нитью X.

В этом случае блокировка должна была предотвращать. Так что делать? Сделать шкафчик a общий объект.

01 static object locker = new object(); 

    ... 

11 lock (locker) 
12 { 
    ... 
15 } 

Теперь, когда поток X достигает линии 11, он получит блокировку и начнет выполнение блока. Когда поток Y достигает строки 11, он попытается получить блокировку на том же объекте, что и поток X. Поскольку этот объект уже заблокирован, поток Y будет ждать, пока блокировка не будет отпущена. Таким образом предотвращается одновременное выполнение блока кода, таким образом защищая любые ресурсы, используемые этим кодом для доступа одновременно.

Примечание: если другие части вашей системы должны быть сериализованы вокруг одних и тех же ресурсов, все они должны попытаться заблокировать один и тот же общий объект-шкафчик.

+0

Еще лучшее объяснение для новичка. Спасибо тебе большое –

+0

Ты так полностью приветствуешь :) –

3

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

Некоторые классы имеют механизмы на них, поэтому вы можете заблокировать их в нескольких местах - примером этого является Hashtable's Syncroot property. Полезностью этого является questionable though. A nice discussion about it is on SO.

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

1

Блокировка не относится к какому-либо объекту - она ​​относится только к куску кода. Поэтому, если у вас есть две разные функции, которые работают с глобальным сокетом, вы должны управлять ими обоими, так как ваш пример должен быть тем же самым объектом «locker», поэтому сделайте его видимым для обоих фрагментов кода.

4

Блокировка влияет только на код в корпусе блокировки. Объекты, переданные как параметр, действуют как уникальный идентификатор, он никак не затрагивается внутренне.

1

Короткий ответ: Нет

Блокировка не является логическим понятием, а не физическое, где язык/процессор выводит объем замка и ограничивает доступ ко всем пунктам в пределах объема. Это ваша работа, чтобы обеспечить использование блокировки, поэтому, если вам нужно приобрести блокировку X для использования ресурса Y, вы должны убедиться, что вы всегда это делаете.

3

Как уже отмечалось всеми здесь ...

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

Но чтобы дать вам краткое представление:

замок не что иное, как замена для Monitor.Enter и Monitor.Exit. Только это, с блокировкой Monitor.Exit, помещается в блок finally.

Итак, что вы: ACTUALLY Замок (в вашем коде) является объектом шкафчика. Таким образом, в любом месте вашего кода, если вы используете этот объект locker для блокировки, этот блок кода будет заблокирован.

Моя догадка это то, как ваш замок работает: (гуру, пожалуйста, поправьте меня, если я ошибаюсь)

if(locker.SyncBlockIndex <0)>              
{                     
//obtain an index to free synch cache block          
//assign the index obtained in previous step to obj.SyncBlockIndex    
}                     
syncblock = syncblockCache[locker.SyncBlockIndex]         
if(!syncblock is owned by the calling thread)          
{                     
//susped the calling thread              
}    

Смотрите, если эта ссылка поможет вам понять замок (я написал этот пост некоторое время назад)

http://dotenetscribbles.blogspot.com/2008/10/calling-monitorenter-recursively.html

2

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

Вы можете проверить ответы на этот вопрос, а также: Does lock(){} lock a resource, or does it lock a piece of code?

Смежные вопросы