pthread_mutex_t VS @ Синхронизированный блок? - PullRequest
6 голосов
/ 27 февраля 2012
static pthread_mutex_t gLock; //global 

pthread_mutex_init(&gLock,NULL); //in init

pthread_mutex_lock(&gLock);
for(int i=0;i<[message count];i++)
CFSetAddValue(mSet, [message objectAtIndex:i]);
pthread_mutex_unlock(&gLock);

Мое приложение какао переходит в не отвечающий режим с pthread_mutex_t.

@synchronized(mSet)
{
for(int i=0;i<[message count];i++)
    CFSetAddValue(mSet, [message objectAtIndex:i]);
}

Мое приложение работает нормально с синхронизированным блоком.

Почему?

Ответы [ 2 ]

8 голосов
/ 27 февраля 2012

Вы сравниваете глобальную блокировку (одну блокировку для всех экземпляров) с рекурсивной блокировкой уровня объекта (одна блокировка на экземпляр, которую можно получить несколько раз из одного и того же потока). Они, как правило, не взаимозаменяемы - они работают и защищают друг от друга очень сильно.

Хорошая новость заключается в том, что вы можете использовать pthread_mutex_t в качестве рекурсивной блокировки, уникальной для каждого экземпляра, для достижения той же степени защиты, что и @synchronized. Использование pthread_mutex_t также значительно ускоряет получение блокировок.

Чтобы добиться того же эффекта, что и @synchronized с использованием мьютекса pthread, объявите pthread_mutex_t gLock в качестве переменной экземпляра, а затем инициализируйте его как рекурсивный мьютекс в -init. Наконец, уничтожьте мьютекс в -dealloc.

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

@synchronized очень медленно по сравнению с рекурсивным мьютексом pthread (последний раз я проверял).

0 голосов
/ 27 февраля 2012

Джастин прав; Однако есть и другая деталь - обработка исключений. От https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html приходит этот совет:

В качестве меры предосторожности блок @synchronized неявно добавляет обработчик исключений в защищенный код. Этот обработчик автоматически освобождает мьютекс в случае возникновения исключения. Это означает, что для использования директивы @synchronized вы также должны включить обработку исключений Objective C в своем коде. Если вы не хотите дополнительных издержек, вызванных неявным обработчиком исключений, вам следует рассмотреть возможность использования классов блокировки.

Если [message count] может вызвать исключения, которые могут перепрыгнуть через ваш код разблокировки и заклинить вас.

...