В чем разница (преимущество и недостаток) между использованием DispatchGroup
и NSRecursiveLock
?
Похоже, они делают то же самое.
В чем разница (преимущество и недостаток) между использованием DispatchGroup
и NSRecursiveLock
?
Похоже, они делают то же самое.
Блокировки и группы служат совершенно разным целям. При работе с рядом параллельных задач:
Блокировка обычно используется для предотвращения/блокировки этих задач от одновременного взаимодействия с некоторым общим ресурсом, не ориентированным на многопотоковое исполнение.
Группа обычно используется для определения того, когда все эти параллельные задачи завершены (независимо от порядка их завершения).
Например, при параллельной обработке серии изображений вы можете использовать блокировку или аналогичный механизм для обновления некоторого свойства (например, массива результатов), тогда как группы диспетчеризации используются, чтобы знать, когда все эти параллельные задачи выполнены.
NSLock
(исходный вопрос) и NSRecursiveLock
, так как оно не кажется уместным при обсуждении блокировок и групп. Разница между этими двумя типами блокировок заключается в том, что один позволяет данному потоку рекурсивно блокироваться, а другой — нет. Но с точки зрения координации между потоками они функционально одинаковы. Но если у вас есть вопросы, касающиеся рекурсивных блокировок, а не нерекурсивных, дайте мне знать.
- person Rob; 26.09.2019
NSLock
на NSRecursiveLock
, возможно, в ответ на ваши замечания «или даже в той же теме». (Кстати, Дмитрий, неуместно изменять вопрос таким образом, чтобы он аннулировал существующие ответы.) Что касается правильности рекурсивных блокировок, они не являются анти-шаблоном, ИМХО, поскольку они являются правильным инструментом для определенных, узких случаев, но, да, они могут быть неправильно использованы как неуклюжие обходные пути для неаккуратного кода блокировки, и, как таковые, часто являются запахом кода.
- person Rob; 27.09.2019
Основное отличие состоит в том, что DispatchGroup
ближе к счетному семафору с обратным вызовом, тогда как NSLock
является простым мьютексом.
Например, DispatchGroup
может быть enter
обработано более одного раза одним или несколькими потоками, а enter
обработка DispatchGroup
никогда не заблокирует вызывающий поток. Вызывающие потоки также отвечают за уравновешивание каждого вызова enter
вызовом leave
. Если в группе зарегистрирован обратный вызов notify
, он будет выполняться, когда количество enter
s минус количество leave
s достигнет 0. Хорошим примером использования DispatchGroup
может быть выполнение нескольких сетевых запросов и наличие одного фрагмента кода обратного вызова. выполняется после того, как все сетевые запросы завершены (или истекло время ожидания и т. д.).
Однако, если один поток lock
получает NSLock
, любой другой поток (или даже тот же самый поток, если уж на то пошло) пытается снова lock
выполнить его до того, как он будет unlock
ed, второй поток будет заблокирован до тех пор, пока не будет unlock
ed (и, возможно, никогда, если вы попробуйте lock
дважды lock
из одной и той же темы). Хорошим примером использования NSLock
является предоставление многопоточного доступа к одному изменяемому элементу данных. В этом случае несколько потоков могут быть уверены, что будут выполнять согласованные операции чтения и записи в/из изменяемого хранилища без потенциального вытеснения друг друга.
NSLock
(и мьютексы в целом) представляют собой примитив синхронизации гораздо более низкого уровня, чем DispatchGroup
. В общем, вы всегда должны использовать примитив самого высокого уровня, который достигает вашей цели. Если DispatchGroup
подойдет, используйте его и игнорируйте NSLock
.