Squeak.ru - шаблоны программирования

Как использовать NSCondition, когда есть два разных места, которые сигнализируют и ждут

Вот псевдокод того, что у меня есть в методе:

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.

Спасибо за ваше время!


Ответы:


1

Самый простой подход с более чем блокировкой - использовать

dispatch_group_t confirmGroup = dispatch_group_create(); // 1

if (requestContacts) {
    dispatch_group_enter(confirmGroup); // 2
    [Extractor requestAccessAddressBook:^(BOOL isComplete) {
        if (isComplete) {
            dispatch_group_leave(confirmGroup); //2
        }
    }];


}
if (requestEvent) {
    dispatch_group_enter(confirmGroup); // 3       
    [Extractor requestAccessEvents:^(BOOL isComplete) {
        if (isComplete) {
            dispatch_group_leave(confirmGroup); // 3
        }
    }];
}
if (requestPhoto) {
    dispatch_group_enter(confirmGroup); // 4
    [Extractor requestAccessPhotos:^(BOOL isComplete) {
        if (isComplete) {
            dispatch_group_leave(confirmGroup); //4
        }
    }];
}
NSLog(@"dispatch_group_wait confirmations");
dispatch_group_wait(confirmGroup, DISPATCH_TIME_FOREVER); // 5
23.12.2014
  • Действительно очень чисто 14.09.2016
  • Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

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

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...