因此,我的应用程序目前可能处于发出网络请求的状态,而当第一个请求仍在等待响应时,可以发出另一个相同的请求。
至少我觉得。根据这个逻辑,看起来线程11首先旋转,然后线程13,然后线程13看起来在等待,因为Thread 11仍然在等待响应
线程11拥有:_dispatch_barrier_sync_f_invoke
,线程13拥有:_dispatch_barrier_sync_f_slow
Thread 11 Crashed:
0 libsystem_kernel.dylib 0x00007fffab4d1dda __pthread_kill + 10
1 libsystem_c.dylib 0x00007fffab437440 abort + 129
2 CrashReporter 0x000000010f28d851 uncaught_exception_handler (PLCrashReporter.m:365)
3 CoreFoundation 0x00007fff963d7e29 __handleUncaughtException + 745
4 libobjc.A.dylib 0x00007fffaaac9b85 _ZL15_objc_terminatev + 94
5 libc++abi.dylib 0x00007fffa9fbdd69 _ZSt11__terminatePFvvE + 8
6 libc++abi.dylib 0x00007fffa9fbdde3 _ZSt9terminatev + 51
7 libobjc.A.dylib 0x00007fffaaac998e objc_terminate + 9
8 libdispatch.dylib 0x00007fffab36d13c _dispatch_client_callout + 28
9 libdispatch.dylib --->0x00007fffab36dd62 _dispatch_barrier_sync_f_invoke + 83
10 Snagit 0x000000010e1a5d68 -[AFURLSessionManager dataTaskWithRequest:completionHandler:] (AFURLSessionManager.m:664)
11 Snagit 0x000000010e19083e -[AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:success:failure:] (AFHTTPSessionManager.m:243)
12 Snagit 0x000000010e18fb0d -[AFHTTPSessionManager GET:parameters:success:failure:] (AFHTTPSessionManager.m:112)
13 Snagit 0x000000010e1d2f29 __51-[TSCAccountHTTPSession GET:parameters:completion:]_block_invoke (TSCAccountHTTPSession.m:317)
14 Snagit 0x000000010e1d464f __58-[TSCAccountHTTPSession performNetworkRequest:completion:]_block_invoke_2 (TSCAccountHTTPSession.m:495)
15 libdispatch.dylib 0x00007fffab375f5f _dispatch_call_block_and_release + 12
16 libdispatch.dylib 0x00007fffab36d128 _dispatch_client_callout + 8
17 libdispatch.dylib 0x00007fffab37c2ce _dispatch_queue_override_invoke + 743
18 libdispatch.dylib 0x00007fffab36eee0 _dispatch_root_queue_drain + 476
19 libdispatch.dylib 0x00007fffab36ecb7 _dispatch_worker_thread3 + 99
20 libsystem_pthread.dylib 0x00007fffab5b9746 _pthread_wqthread + 1299
21 libsystem_pthread.dylib 0x00007fffab5b9221 start_wqthread + 13
Thread 13:
0 libsystem_kernel.dylib 0x00007fffab4d23b6 __ulock_wait + 10
1 libdispatch.dylib 0x00007fffab385c6e _dispatch_thread_event_wait_slow + 85
2 libdispatch.dylib --->0x00007fffab3785ea _dispatch_barrier_sync_f_slow + 402
3 Snagit 0x000000010e1a5d68 -[AFURLSessionManager dataTaskWithRequest:completionHandler:] (AFURLSessionManager.m:664)
4 Snagit 0x000000010e19083e -[AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:success:failure:] (AFHTTPSessionManager.m:243)
5 Snagit 0x000000010e18fb0d -[AFHTTPSessionManager GET:parameters:success:failure:] (AFHTTPSessionManager.m:112)
6 Snagit 0x000000010e1d2f29 __51-[TSCAccountHTTPSession GET:parameters:completion:]_block_invoke (TSCAccountHTTPSession.m:317)
7 Snagit 0x000000010e1d464f __58-[TSCAccountHTTPSession performNetworkRequest:completion:]_block_invoke_2 (TSCAccountHTTPSession.m:495)
8 libdispatch.dylib 0x00007fffab375f5f _dispatch_call_block_and_release + 12
9 libdispatch.dylib 0x00007fffab36d128 _dispatch_client_callout + 8
10 libdispatch.dylib 0x00007fffab37c2ce _dispatch_queue_override_invoke + 743
11 libdispatch.dylib 0x00007fffab36eee0 _dispatch_root_queue_drain + 476
12 libdispatch.dylib 0x00007fffab36ecb7 _dispatch_worker_thread3 + 99
13 libsystem_pthread.dylib 0x00007fffab5b9746 _pthread_wqthread + 1299
14 libsystem_pthread.dylib 0x00007fffab5b9221 start_wqthread + 13
下面是包含AFNetworking的dispatch_sync
代码
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
__block NSURLSessionDataTask *dataTask = nil;
dispatch_sync(
url_session_manager_creation_queue(), ^{
dataTask = [self.session dataTaskWithRequest:request];
}
);
[self addDelegateForDataTask:dataTask completionHandler:completionHandler];
return dataTask;
}
static dispatch_queue_t url_session_manager_creation_queue() {
static dispatch_queue_t af_url_session_manager_creation_queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
af_url_session_manager_creation_queue = dispatch_queue_create("com.alamofire.networking.session.manager.creation", DISPATCH_QUEUE_SERIAL);
});
return af_url_session_manager_creation_queue;
}
发布于 2017-01-06 03:23:42
我希望下面能回答你的问题。但是,如果您的程序中有一个要调试的错误,并且相同的请求被发出了两次,这是事实,那么这不是包含错误的代码。
GCD
使用所谓的屏障来同步调度队列上的块,请看这里的文档:派单和异步
屏障确保队列上的屏障块相互排斥,即它单独执行。
调度屏障允许您在并发调度队列中创建同步点。当遇到障碍时,并发队列会延迟屏障块(或任何其他块)的执行,直到所有块在屏障完成执行之前提交。在这一点上,屏障块自行执行。完成后,队列将恢复其正常执行行为。
如果队列是串行的,或者是全局并发队列,那么:
来自dispatch_barrier_sync:如果传递给该函数的队列是一个串行队列或一个全局并发队列,则此函数的行为类似于dispatch_sync函数。
实际上,dispatch_sync
委托给dispatch_barrier_sync_*
,调用堆栈看起来如下所示:
// some inline functions omitted here
_dispatch_barrier_sync_f_invoke
_dispatch_barrier_sync_f
dispatch_sync_f
dispatch_sync
现在,如果运行时沿途无法获得另一个块的当前线程的屏障,那么它就走了slow
路。这将为您和调用线程等待设置所有同步。在队列再次空闲的event
上,线程继续执行下一个块。
基本上,它是相同的调用堆栈,但沿途有一个弯路,带有一些锁(信号量),然后返回到_dispatch_barrier_sync_f_invoke
。
// again, some inline functions omitted here
_dispatch_barrier_sync_f_invoke
_dispatch_thread_event_wait
_dispatch_barrier_sync_f_slow
// here _dispatch_queue_try_acquire_barrier_sync fails...
_dispatch_barrier_sync_f
dispatch_sync_f
dispatch_sync
如果您想了解更多关于GCD
__的知识,那么最好的了解内部机制的地方是它的源代码https://github.com/apple/swift-corelibs-libdispatch。
https://stackoverflow.com/questions/41049700
复制相似问题