7

Я обсуждаю, следует ли перейти к шаблону на основе GCD для многопоточных аксессуаров. Я использую пользовательскую синхронизацию на основе блокировки в аксессорах в течение многих лет, но я нашел некоторую информацию (Intro to GCD), и, похоже, существуют плюсы подхода на основе GCD. Я надеюсь начать диалог здесь, чтобы помочь себе, а другие взвешивают решение.Многопоточные объективы Objective-C: GCD vs locks

картина выглядит следующим образом:

- (id)something 
{ 
    __block id localSomething; 
    dispatch_sync(queue, ^{ 
     localSomething = [something retain]; 
    }); 
    return [localSomething autorelease]; 
} 

- (void)setSomething:(id)newSomething 
{ 
    dispatch_async(queue, ^{ 
     if(newSomething != something) 
     { 
      [something release]; 
      something = [newSomething retain]; 
      [self updateSomethingCaches]; 
     } 
    }); 
} 

На про стороне: вы получаете преимущество, возможно, не блокируя доступ на запись; более низкие накладные расходы, чем блокировки (возможно?); безопасность от забывания до разблокировки перед возвратом из критических разделов кода; другие?

Недостатки: Обработка исключений не существует, поэтому вам необходимо закодировать ее в каждом блоке, в котором она может понадобиться.

Является ли этот шаблон потенциально рекомендуемым методом написания многопоточных аксессуаров?

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

Любая информация/понимание будет оценено по достоинству.

+0

Точно так же, как точки данных, очереди и блокировки pthread имеют одинаковый «вес» (80 байт против 64 байт, сопоставимое время сбора данных), но использование очередей вместо явных потоков экономит проводную память для потоков на стороне ядра (если только вы тщательно управляйте своими явными потоками жизни через какой-то пул) –

ответ

8

Является ли этот шаблон потенциально рекомендуемым методом записи многопоточных аксессуаров?

Я думаю, вы написали это с последовательной очередью, но для этого нет оснований. Рассмотрите это:

dispatch_queue_t queue = dispatch_queue_create("com.example", DISPATCH_QUEUE_CONCURRENT); 

// same thing as your example 
- (NSString*)something { 
    __block NSString *localSomething; 
    dispatch_sync(queue, ^{ 
     localSomething = _something; 
    }); 
    return localSomething; 
} 

- (void)setSomething:(NSString*)something { 
    dispatch_barrier_async(queue, ^{ 
     _something = something; 
    }); 
} 

Он читает одновременно, но использует барьер отправки для отключения параллелизма во время записи. Большим преимуществом GCD является то, что позволяет одновременное чтение вместо блокировки всего объекта, как @property (атомный).

Оба асинхронных объекта (dispatch_async, dispatch_barrier_async) быстрее с клиентской точки зрения, но медленнее, чем синхронизация, поскольку они должны копировать блок и иметь блок такой маленькой задачи, время, необходимое для копирования становится значимым. Я скорее вернусь к клиенту, поэтому с ним все в порядке.

+0

Барьеры не работают в глобальных очередях. Вам понадобится приватная параллельная очередь. –

+0

О, правда, это на документах, я исправлю это, спасибо. – Jano

+0

Также вы можете использовать dispatch_async_f, чтобы избежать Block_copy() –

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