#ios #objective-c #multithreading #concurrency #grand-central-dispatch
#iOS #objective-c #многопоточность #параллелизм #grand-central-dispatch
Вопрос:
Предположим, я вызываю приведенный ниже метод в основном потоке. Если какой-либо другой поток выполняет запись в массив во время вызова метода, dispatch_sync заблокируется. Но он блокируется в другой очереди (не в основной очереди). Когда это заблокировано, каково состояние основной очереди (метод не может двигаться вперед, пока не вернется disaptch_sync, но рассматривается ли это как асинхронный вызов в основной очереди). очередь). Например: будет ли основная очередь реагировать на события пользовательского интерфейса? Если да, что произойдет с состоянием вызова метода, когда dispatch_sync возвращается, когда происходит реакция на событие пользователя?
-(id) objectAtIndex:(NSUInteger)index
{
__block id obj;
dispatch_sync(self.dataAccessQ, ^{
obj = self.embeddedArray[index];
});
return obj;
}
Ответ №1:
Не имеет значения, является ли это основной очередью или нет. Любая очередь, используемая для вызова objectAtIndex:
, будет блокировать dispatch_sync
вызов до его завершения.
Если вы вызываете этот код в основной очереди, он блокируется, как и любая другая очередь. В течение этого времени никакие пользовательские события обрабатываться не будут. Пользовательский интерфейс будет отображаться заблокированным в течение этого времени. По завершении пользовательский интерфейс снова будет работать в обычном режиме.
Комментарии:
1. Используя параллельную очередь, другие задачи в этой очереди могут продолжать выполняться.
2. @AminNegm-Awad Если
objectAtIndex:
вызывается из параллельной очереди, а параллельная очередь использует несколько потоков, то поток, используемый для обработкиobjectAtIndex:
метода, будет заблокирован во времяdispatch_sync
использования. Другие потоки (если таковые имеются), используемые параллельной очередью, не будут затронуты. Но основная очередь — это последовательная очередь, поэтому ничего из этого не применяется.3. Спасибо @rmaddy Итак, в заключение, если я создаю потокобезопасный массив, похоже, что я мало что могу сделать, кроме как спроектировать так, чтобы никакие записи не занимали слишком много времени.
4. Это было бы совсем другое обсуждение. Я бы провел некоторое исследование потокобезопасных массивов и, при необходимости, опубликовал новый вопрос, касающийся любых проблем, которые у вас есть с этим.
5. спасибо @rmaddy. Подойдет. Любые указатели на хороший дизайн потокобезопасного массива?
Ответ №2:
Нет, основная очередь тоже заблокирована.
Основная очередь привязана к основному потоку. Каждый поток может выполнять один и только один поток управления одновременно. Если какой-либо код выполняется в основном потоке, никакой другой код не может быть выполнен.
Поэтому ожидание результата операции, подписанной на другую очередь, заблокирует ожидающий поток. (Не параллельный Q!) Вот почему у нас есть обработчики завершения.
Вместо возврата объекта добавьте параметр для обработчика завершения в свой метод и вызовите его внутри блока в конце.
Комментарии:
1. Спасибо. Я пытаюсь создать потокобезопасный массив. Итак, мне нужно переопределить objectAtIndex и не могу добавить параметры. Какие-либо обходные пути для этого случая (например, подход блока завершения)?
2. Вам действительно следует еще раз подумать о том, чтобы иметь потокобезопасный массив. Это похоже на атомарные свойства, которые не решают большинство проблем с параллельным выполнением. Обычно вам нужен объект, управляющий содержимым массива, и очередь, которая позволяет вам сериализовать код, который шире простого доступа.