Подтвердить что ты не робот

Конструкция блокировки чтения/записи?

Я опытный .NET-программист и растягиваю ноги с помощью iOS. Одна из моих любимых многопотоковых конструкций в .NET - ReaderWriterLock. Это позволяет использовать несколько считывателей или один писатель. Одна особенность, которую я действительно пропускаю в iOS, заключается в том, что блокировки являются повторными. То есть, потоки чтения могут приобретать блокировку чтения несколько раз, пока они выпускают ее столько же раз. Аналогично, поток одиночной записи может получить блокировку несколько раз, пока она освобождает блокировку на эквивалентное число.

Я заглянул в iOS Framework, и ни одна из конструкций не предлагает такую ​​же поддержку, как и повторное подключение. Я также заглянул в библиотеку pthread. Я нашел rwlock, но он не позволяет повторного входа.

Есть ли что-нибудь в iOS, которое позволяет блокировать чтение и запись для повторного входа?

4b9b3361

Ответ 1

Из iOS Руководство по программированию потоков:

Система поддерживает блокировку чтения и записи, используя только потоки POSIX. Для получения дополнительной информации о том, как использовать эти блокировки, см. Справочную страницу pthread.

Итак, я думаю, что если pthreads не поддерживают повторное включение, ответ будет отрицательным.

Ответ 2

Да, директива @synchronized является реентерабельной. См. Использование @synchronized Directive в руководстве по программированию потоков, а также Threading на языке программирования ObjC.

Тем не менее, вы почти никогда не должны использовать это в iOS. В большинстве случаев вы можете избежать блокировок всех видов, не говоря уже о очень тяжелых (медленных) замках, таких как фиксаторы реентера. См. Руководство по программированию Concurrency и, в частности, раздел "Миграция из потоков" , для получения обширной информации о подходах на основе очереди, которые iOS поддерживает в ручном режиме управления и блокировки.

Например, блокировка чтения/записи работает так, используя Grand Central Dispatch:

- (id)init {
   ...
   _someObjectQueue = dispatch_queue_create("com.myapp.someObject", 
                                            DISPATCH_QUEUE_CONCURRENT);
 }

// In iOS 5 you need to release disptach_release(_someObjectQueue) in dealloc,
// but not in iOS 6.

- (id)someObject {
  __block id result;
  dispatch_sync(self.someObjectQueue, ^{
    result = _someObject;
  });
  return result;
}

- (void)setSomeObject:(id)newValue {
  dispatch_barrier_async(self.queue, ^{
    _someObject = newValue;
});

Этот подход позволяет неограниченным параллельным читателям с исключительными писателями, гарантируя, что писатели никогда не голодают и что записи и чтения являются сериализованными, и при этом избегают любых вызовов ядра, если нет фактического утверждения. Это все, чтобы сказать это очень быстро и просто.

Когда приходит читатель, вы ставите в очередь запрос на чтение значения и ожидаете его обработки. Когда приходит писатель, он ставит в очередь запрос на барьер, чтобы обновить его, что требует, чтобы в настоящее время не выполняются другие запросы из этой очереди. С помощью этой конструкции разработчику не нужно управлять замками. Просто поместите вещи в очередь в том порядке, в котором вы хотите их запустить.