Вот псевдокод того, что у меня есть в методе:
NSCondition condition = [[NSCondition alloc] init];
int predicate = 0;
dispatch_sync(dispatch_get_main_queue(), ^
{
[condition lock]; // Lock-0
});
bindBlock1ForDataReceived(^()
{
// Not main thread here.
// Get on main thread, because lock and unlock must be run on same thread.
dispatch_sync(dispatch_get_main_queue(), ^
{
predicate = 1;
[condition signal];
[condition unlock]; <<<<---- "unlocked when not locked"
});
});
bindBlock2ForNoDataAvailable(^()
{
// Not main thread here.
// Get on main thread, because lock and unlock must be run on same thread.
dispatch_sync(dispatch_get_main_queue(), ^
{
predicate = 2;
[condition signal];
[condition unlock];
});
});
[condition lock]; // Lock-1
while (predicate == 0)
{
[condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.0]];
}
[condition unlock];
if (predicate == 2)
{
[condition lock]; // Lock-2
[condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
[condition unlock];
}
Проблема в том, что я получаю предупреждение «разблокировано, когда не заблокировано» от iOS (см. Выше), когда сначала происходит событие 2, а затем событие 1.
Теперь позвольте мне объяснить, что я пытаюсь сделать: это часть сборщика данных. Принимаются данные обычных случаев и выполняется блок 1: проблем нет. Иногда сначала ложно выполняется блок 2 без данных, за которым вскоре следует блок 1; это когда я получаю предупреждение NSCondition
. Чтобы поймать этот редкий случай, я жду 2.0
секунды. Вот что происходит:
- Block2 сигнализирует о состоянии.
- Замок-1 проваливается.
predicate
больше не0
, так что ждать нечего.- Состояние снова разблокировано.
- Затем мы переходим к
if
-утверждению, условие(predicate == 2)
которого истинно. - Метод немедленно получает Lock-2. <<<< ОСНОВНАЯ ПРИЧИНА
- Затем метод ждет
2.0
секунд. - В течение этих 2 секунд выполняется блок 1 и сигнализирует условие.
- Затем block1 разблокирует условие и метод.
Основная причина (см. выше) заключается в том, что блокировка получена методом (работником/потребителем), в то время как она должна была быть получена производителем данных. Я потратил много времени, пытаясь понять это; одна из мыслей, которые у меня были, это использование двух NSCondition
, но я не мог понять это, потому что вещи довольно переплетены.
Примечание. Мне кажется странным, что предупреждение не появляется в unlock
внутри оператора if
.
Спасибо за ваше время!