代码在同一线程上的dispatch_async中运行两次-目标C,iOS

时间:2018-09-05 15:07:02

标签: ios objective-c

我有一个从网络接收数据时会被调用的方法。出于好奇,我保留了一个计数器来检查对同一线程的异步调用是否同步。我知道它很蠢,但是我发现了一些奇怪的东西。

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 :(得分:2)

分派队列有两种。

  • 序列
  • 并发

一个串行队列(如主队列)一次执行您所排队的已关闭的闭包。

但是,并发队列(如全局调度队列)可以并发执行闭包。 (看看Apple documentation

在相同的计数器编号被打印两次的情况下,第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];
});

仅供参考,这称为synchronization。您应该synchronize编写代码,以使critical section(例如添加计数器或写入文件)不会被两个以上的线程同时访问。