Отвечая на ваш вопрос, блокировки, как правило, «справедливы» (когда любой поток не будет голодать). Заметным исключением является os_unfair_lock
(и оно прямо в названии). Но нечестные замки были введены по причине, а именно их эффективности. Использование недобросовестных блокировок для синхронизации иллюстрируется в Параллельное программирование с GCD в видео Swift 3 WWDC. Но в целом справедливость блокировки не является проблемой в большинстве сценариев синхронизации.
При этом Apple предлагает отойти от блокировок и вместо этого синхронизировать с GCD. Блокировки «значительно легче использовать». Поскольку в этом видео говорится:
С GCD ваш код будет работать в определенной области, что означает, что вы не можете забыть разблокировать. Другое дело, что на самом деле очереди лучше интегрированы со временем выполнения в Xcode в инструментах отладки.
GCD устраняет любую двусмысленность в отношении справедливости синхронизации, поскольку это, очевидно, строго FIFO.
Итак, простое решение - использовать последовательную очередь GCD. Более продвинутым решением является использование шаблона reader-writer , который достигается с помощью параллельной очереди GCD, в которой один выполняет чтение синхронно (но одновременно с другими операциями чтения в этой очереди), но выполняет запись асинхронно с барьером (не совпадает с чем-либо еще в этой очереди).
Итог, хотя мы часто используем GCD для простой синхронизации, ваши блокировки - совершенно адекватный механизм. Директива @synchronized
проста, но вы не увидите, чтобы она использовалась так часто, потому что она немного менее эффективна (хотя и наблюдаема только при выполнении миллионов синхронизаций).
Я мог бы предложить статью Майка Эша Замки, безопасность резьбы и Swift: издание 2017 года . Опять же, не отчаивайтесь стремительностью статьи или вышеупомянутого видео, так как большая часть его в равной степени применима к Objective-C.
Само собой разумеется, если вы можете, вы должнысвести к минимуму то, что синхронизация в целом. Как указывает Apple в своем Руководстве по программированию потоков: Синхронизация :
Избегайте синхронизации вообще
Для любых новых проектов, над которыми вы работаете, и даже для существующих проектов,проектирование вашего кода и структур данных, чтобы избежать необходимости в синхронизации, является наилучшим возможным решением. Хотя блокировки и другие инструменты синхронизации полезны, они влияют на производительность любого приложения. И если общий дизайн вызывает высокую конкуренцию между конкретными ресурсами, ваши потоки могут ожидать еще дольше.
Лучший способ реализовать параллелизм - это уменьшить взаимодействия и взаимозависимости между вашими параллельными задачами. Если каждая задача работает со своим собственным набором личных данных, ей не нужно защищать эти данные с помощью блокировок. Даже в ситуациях, когда две задачи совместно используют общий набор данных, вы можете посмотреть на способы разделения этого набора или предоставить каждой задаче свою собственную копию. Конечно, копирование наборов данных также имеет свои издержки, поэтому вам необходимо сопоставить эти затраты с затратами на синхронизацию, прежде чем принимать решение.