VB.net SyncLock Object
Я всегда видел на примерах SyncLock людей, использующих
Private Lock1 As New Object ' declaration
SyncLock Lock1 ' usage
но почему? В моем конкретном случае я блокирую очередь, чтобы избежать проблем при многопоточном постановке в очередь и снятии очереди с моих данных.
Могу ли я заблокировать сам объект Queue, как это?
Private cmdQueue As New Queue(Of QueueItem) ' declaration
SyncLock cmdQueue ' usage
Любая помощь приветствуется. Благодарю.
редактировать:
спасибо за все ответы, но ответ tcarvin был тем, что я искал. Очередь является частной от моего одноэлементного объекта Comms, который ставит в очередь новые сообщения для отправки (предоставляемые методом Send), очередь используется в рабочем потоке в этом объекте по одному сообщению за раз, и единственный код, который у меня есть внутри блокировок: один звонок в Enqueue и Dequeue.
4 ответа
Мудрый совет от других авторов наверняка. Но ответ - да, вы можете использовать объект Queue для блокировки. Вы можете использовать любой объект. И в своем фрагменте кода вы объявили свой экземпляр очереди закрытым, так что вы, скорее всего, избежите обычной проблемы, связанной с блокировкой кем-либо вашего объекта очереди (при условии, что вы не пропустите объект за пределами вашего класса). Однако лучшие практики предполагают использование выделенного объекта таким образом, чтобы в будущем кто-то не изменил ваш код, а затем открыл этот объект очереди, используемый для блокировки.
Это распространенное заблуждение о замках. Задача блокировки - блокировать код, а не придавать потокобезопасности объекту. Объект существует только для отслеживания состояния блокировки. А поскольку вы хотите заблокировать определенный фрагмент кода, вам понадобится определенный объект для хранения состояния блокировки. Публичная очередь не является достаточно конкретной, она обязательно будет использоваться другим кодом где-то еще. И если он также неправильно использует объект очереди, чтобы заблокировать свой собственный код, то шансы на неприятную проблему взаимоблокировки высоки.
Идея блокировки объектов для обеспечения безопасности потоков действительно существует, она является предметом интенсивных исследований, которые, кажется, никогда не доходят до моей машины. Это называется STM, "программная транзакционная память". Статья в Википедии здесь.
Проблема в том, что другие могут заблокировать ваш объект, и он будет вне вашего контроля. Ознакомьтесь с рекомендациями Microsoft по этому заявлению о блокировке
Я думаю, что то, что вы делаете, является плохой практикой, поскольку заблокированный объект должен оставаться неизменным. Так как вы фиксируете на Queue(Of QueueItem)
и затем вы удаляете очередь из той же очереди, затем объект изменяется и, как указано здесь: https://msdn.microsoft.com/en-us/library/3a86s51t.aspx (2-е правило),
Механизм требует, чтобы объект блокировки оставался неизменным.
Так что вы должны сделать это Public StatusObject As New Object
и заблокировать его