我有一个从网络接收数据时会被调用的方法。出于好奇,我保留了一个计数器来检查对同一线程的异步调用是否同步。我知道它很蠢,但是我发现了一些奇怪的东西。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"counterForAsync=%d",counterForAsync);
++counterForAsync;
if (file) {
[file seekToEndOfFile];
}
[file writeData:data];
});
我复制了控制台日志,并对其进行了高级检查,发现重复了几行。
在其他几行中也有相同的内容。 如果它运行了两次,那么就不好了,因为我正在异步线程中执行文件操作。
答案 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
(例如添加计数器或写入文件)不会被两个以上的线程同时访问。