Java, конечно, развивался очень медленно - особенно при сравнении его с C# и VB. Я лично чувствую, что они приняли неправильное решение с дженериками с точки зрения хранения обратной совместимости за счет безопасности времени выполнения и эффективности. Подход.NET работает намного лучше в [почти 111] каждый путь, IMO.
Java 7 имеет длинный список потенциал функции - и язык и платформа - но это было ужасно долгое время в процессе создания, и существуют все еще значительные вопросительные знаки по многим функциям.
я не хотел бы возлагать любую "вину" на то, почему это произошло, как бы то ни было.
Оператор блокировки НЕ является «кодом блокировки» или каким-либо ресурсом, который находится между фигурными скобками.
Я считаю, что лучше всего понимать блокировку с точки зрения потока (в конце концов, сценарии потоковой передачи - это когда вам необходимо рассмотреть возможность блокировки.
Учитывая ваш пример кода
10 locker = new object();
11 lock (locker)
12 {
...
15 }
Когда поток X достигает строки 10, создается новый объект, а в строке 11 устанавливается блокировка объекта. Поток X продолжает выполнять любой код внутри блока.
Теперь, когда поток X находится в середине нашего блока, поток Y достигает строки 10. И вот, создается новый объект, и, поскольку он создан потоком Y, в настоящее время для этого объекта не используется блокировка. Таким образом, когда поток Y достигает 11, он успешно получает блокировку объекта и продолжает выполнять блок одновременно с потоком X.
Это ситуация, которую блокировка должна была предотвратить. Так что делать? Сделайте шкафчик общим объектом .
01 static object locker = new object();
...
11 lock (locker)
12 {
...
15 }
Теперь, когда поток X достигает строки 11, он получает блокировку и начинает выполнение блока. Когда поток Y достигает строки 11, он попытается получить блокировку того же объекта, что и поток X. Поскольку этот объект уже заблокирован, поток Y будет ждать, пока блокировка не будет снята. Таким образом предотвращается одновременное выполнение блока кода, тем самым защищая любые ресурсы, используемые этим кодом, для одновременного доступа.
Примечание: если другие части вашей системы должны быть сериализованы вокруг одних и тех же ресурсов, все они должны попытаться заблокировать один и тот же общий шкафчик объект.
Блокировка влияет только на код в теле инструкции блокировки. Объекты, переданные в качестве параметра, действуют как уникальный идентификатор, на него не влияют никакие внутренние факторы.
Это очень просто - замок блокирует код внутри замка заявление. Если вы используете эти ресурсы в другом месте своего кода, они не будут охвачены этой блокировкой.
Некоторые классы имеют механизмы на них, поэтому вы можете заблокировать их в нескольких местах - примером этого является свойство Syncroot Hashtable. . Однако полезность этого сомнительна . Хорошее обсуждение этого вопроса находится на SO .
Лучше всего инкапсулировать эту логику в отдельный класс с внутренним механизмом блокировки и убедиться, что ваше приложение использует только этот класс.
Блокировка - это просто токен. Пока какой-то поток удерживает определенную блокировку, другим потокам не будет разрешено получить эту блокировку и таким образом можно предотвратить запуск кода, который синхронизируется с использованием рассматриваемой блокировки.
Вы также можете проверить ответы на этот вопрос: Блокирует ли lock () {} ресурс,или он блокирует фрагмент кода?
Блокировка не относится к какому-либо объекту - она относится только к фрагменту кода. Итак, если у вас есть две разные функции, которые работают с глобальным сокетом, вы должны контролировать их обе, в вашем примере это должен быть один и тот же объект «шкафчик» - так что сделайте его видимым для обоих фрагментов кода.
Краткий ответ: Нет
Блокировка - это логическая концепция, а не физическая, когда язык / ЦП определяет объем блокировки и ограничивает доступ ко всем элементам в этой области. Ваша задача - принудительно использовать блокировку, поэтому, если вам нужно получить блокировку X для использования ресурса Y, вы должны убедиться, что вы всегда это делаете.
Фактически, как только вы назначаете им идентификатор, они становятся общедоступной переменной-членом данного элемента. Так, например, если у вас есть
<mx:Canvas><mx:Label id="myLabel" /></mx:Canvas>
, вы можете получить к нему доступ по его id в качестве имени переменной:
myLabel.text = "Hello world!";
Дайте мне знать, если вам нужны дополнительные разъяснения. Если это не то, о чем вы спрашиваете, не стесняйтесь комментировать, и я сделаю еще один удар.
С уважением,
Но чтобы дать вам краткое представление:
блокировка - не что иное, как замена Monitor.Enter
и Monitor.Exit
. Только это с блокировкой Monitor.Exit
помещается в блок finally.
Итак, то, что вы ДЕЙСТВИТЕЛЬНО блокируете (в вашем коде), является объектом шкафчика. Итак, в любом месте вашего кода, если вы используете этот объект-шкафчик для блокировки, этот блок кода будет заблокирован.
Я предполагаю, что ваша блокировка работает так: (гуру, пожалуйста, поправьте меня, если я ошибаюсь)
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