2013-11-25 2 views
4

Я только что прочитал this post, и его решение кажется убедительным:Как реализовать механизм блокировки ретентата через параллельную очередь отправки (GCD)?

  • Последовательная очередь используется для синхронизации доступа
  • dispatch_get_specific/dispatch_set_specific используется для обеспечения возможности reentrance.

Меня интересует на это, если можно продвигать эту схему реализовать механизм возвратного запирающий для параллельной очереди отправки (каждый чтение осуществляется с помощью dispatch_sync, запись производится с использованием dispatch_barrier_async, как описано here, see "One Resource, Multiple Readers, and a Single Writer") ,

P.S. Я думаю, что мне удалось реализовать это, используя [NSThread currentThread].threadDictionaryhere, но мне не нравится иметь дело с [NSThread currentThread], так как я полагаюсь на GCD. Можно ли заменить использование [NSThread currentThread].threadDictionary некорректным кодом dispatch_set_specific/dispatch_get_specific?

+0

Это сообщение немного устарело, но есть ли причина, по которой вы не можете просто использовать dispatch_get_specific для того, что вы пытаетесь сделать? Если вы создаете параллельную диспетчерскую очередь (вместо того, чтобы использовать глобальную), не могли бы вы просто сделать то же самое? – JPC

+0

@JPC, кажется, что вы правы. Слишком долго, чтобы описать мою ошибку (почему я чувствовал, что это был другой случай) ... Не стесняйтесь отформатировать этот комментарий в качестве ответа, и я буду считать его правильным. –

+0

Спасибо за это, кстати! Теперь я могу вернуться к исходному коду и устранить все это [NSThread currentThread]. –

ответ

6

Вы запросили меня в комментарии к связанному сообщению, если я прокомментирую этот вопрос. Извините, я так долго, но я помню, как в первый раз, когда я смотрел на него, я не чувствовал, что у меня есть что-то полезное. Но мне сегодня напомнили эту тему и ответили на этот вопрос, и решили, что я сделаю снимок:

В общем, я бы предложил не идти по этой дороге вообще. Как я объяснил в the linked-to/from answer, реализация рекурсивного «замка» с dispatch_get/set_specificникогда не пуленепробиваемая и выходящая за рамки простого последовательного случая к семантике с одним писателем/многими читателями dispatch_barrier_[a]sync не удалит эти проблемы и вероятно, вызовет еще больше проблем.

Как и в сторону, если вы просто ищете альтернативу [NSThread threadDictionary] для локальной памяти потока, возможно, в форме, не Objective-C API, то вы должны использовать pthread_setspecific и pthread_getspecific. Это нижестоящие POSIX-вызовы, на которых построено (почти наверняка) [NSThread threadDictionary].

Отступив на минутку: среди программистов-ветеран-систем есть довольно сильное чувство, что рекурсивные блокировки являются анти-паттернами с самого начала, и их следует избегать. Вот interesting treatise on the subject. (Если вас не интересует апокрифическая история о том, почему в POSIX существуют рекурсивные мьютексы, просто найдите «объективные факты», чтобы перейти к той части, которая имеет отношение к этому вопросу.) Этот фрагмент написан в терминах более примитивных «замков» »(состоящие из мьютексов и условий), которые принципиально отличаются от очередей, несмотря на то, что очереди могут (иногда весьма полезными) адаптироваться для имитации блокировок в некоторых распространенных случаях. Однако, несмотря на то, что они отличаются друг от друга, если учесть критику, которую Butenhof взимает с рекурсивных примитивных блокировок, быстро становится очевидным, что во многих способах, которые рекурсивные блокировки «плохие», использование очередей для имитации блокировок хуже. Например, на самом базовом уровне единственным способом, которым вы можете разблокировать блокировку с блокировкой по очереди, является возврат; есть нет другого способа, чтобы освободить блокировку на основе очереди. Вызов другого кода, который может потребовать рекурсивного повторного ввода этой блокировки, в то время как вызывающий абонент продолжает ее удерживать, является потенциально неограниченным расширением времени блокировки.

Общая рекомендация, которая послужила мне хорошим, «Используйте абстракцию высочайшего уровня, которая выполняет свою работу.«В контексте этого вопроса это переведет (отбросив вышеупомянутую критику рекурсивной блокировки на данный момент): если вы работаете в Objective-C и по какой-то причине хотите рекурсивные блокировки, просто используйте @synchronized. при анализе производительности говорит вам, что использование @synchronized фактически вызывает вас проблемы, затем посмотреть в лучшие решения (с предвидением, чтобы знать, что «лучшие решения», вероятно, потребует отходя от рекурсивных замков все вместе.)

В целом, попытка адаптировать поведение параллельного режима ожидания GCD для имитации рекурсивного блокировки чтения/записи выглядит как проигрышное предложение. В лучшем случае всегда будут применяться ограничения, которые я объяснил over here для серийного случая. В худшем случае вы промульгатин g шаблон, который в конечном итоге уменьшает параллелизм.

+1

Большое вам спасибо за ваш ответ @ipmcc! Мне нужно время, чтобы прочитать и понять все, что вы указали мне. Кстати, вы один из лучших писателей здесь, на SO. –

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