Код, выполняющийся дважды в dispatch_async в одном и том же потоке - цель c, ios - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть метод, который вызывается при получении данных из сети. Просто из любопытства я держал счетчик, чтобы проверить, являются ли асинхронные вызовы того же потока синхронными. Я знаю, что это глупо, но я нашел что-то странное.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSLog(@"counterForAsync=%d",counterForAsync);
            ++counterForAsync;
            if (file)  {
                [file seekToEndOfFile];
            }
            [file writeData:data];
});

Я скопировал консольный журнал и заметил его в возвышенном виде, и увидел, что некоторые строки были повторены .

enter image description here

enter image description here

То же самое в нескольких других строках. Если он выполняется дважды, это плохо, потому что я выполняю файловую операцию в асинхронном потоке.

1 Ответ

0 голосов
/ 05 сентября 2018

Существует два типа очередей отправки.

  • серийный
  • одновременно

Последовательная очередь (как и основная очередь) выполняет закрытые очереди «по порядку», которые вы ставите в очередь, по одной за раз.

Однако параллельная очередь (например, глобальная очередь отправки) выполняет одновременные замыкания. (Взгляните на документацию Apple )

В тех случаях, когда один и тот же номер счетчика печатается дважды, 309-е замыкание NSLogged счетчик до 308-го замыкания добавляет 1 к счетчику. (Ты понял?)

Так что для операции записи в файл вы должны использовать serial queue, как показано ниже, как указано в документации

Последовательные очереди часто используются для синхронизации доступа к определенному ресурсу.

dispatch_queue_t serialQueue = dispatch_queue_create("com.myqueue.filewrite", DISPATCH_QUEUE_SERIAL);

dispatch_async(serialQueue, ^{
    NSLog(@"counterForAsync=%d",counterForAsync);
        ++counterForAsync;
        if (file)  {
            [file seekToEndOfFile];
        }
        [file writeData:data];
});

К вашему сведению, это называется синхронизация . Вы должны synchronize свой код, чтобы ваш critical section (например, добавление счетчика или запись в файл) не был доступен более чем двум потокам одновременно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...