dispatch_sync

本文详细解析了dispatch_async与dispatch_sync两个函数的区别与应用场景。dispatch_async以非同步方式追加Block,不等待执行;而dispatch_sync则同步追加Block,并等待其执行完毕。文章还列举了几种可能引发死锁的情况。
//dispatch_async函数将指定的Block"非同步"的追加到指定的Dispatch Queue中,dispatch_async函数不作任何等待。
//dispatch_sync函数将指定的Block"同步"追加到指定的Dispatch Queue中。在追加Block结束之前,dispatch_sync函数会一直等待。即一旦调用dispatch_sync函数,那么在指定的处理执行结束之前,该函数不会返回。
//dispatch_sync函数出现的死锁问题:
//a.该源代码在Main Dispatch Queue即主线程中执行指定的Block,并等待其执行结束。而其实主线程中正在执行这些源代码,所以无法执行追加到Main Dispatch Queue 的Block。
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"hello");
});
//b.Main Dispatch Queue中执行的Block等待Main Dispatch Queue中要执行的Block执行结束
dispatch_queue_t queue2 = dispatch_get_main_queue();
dispatch_async(queue2, ^{
dispatch_sync(queue2,^{
NSLog(@"hello");
});
});
//c.Serial Dispatch Queue 也会引起相同的问题
dispatch_queue_t queue3 = dispatch_queue_create("Dispatch Queue的名称", NULL);
dispatch_async(queue3, ^{
dispatch_sync(queue3, ^{
NSLog(@"hello");
});
});

Thread 0 name: Thread 0: 0 libsystem_kernel.dylib 0x00000001fe63bc84 mach_msg2_trap + 8 (:-1) 1 libsystem_kernel.dylib 0x00000001fe64eb54 mach_msg2_internal + 80 (mach_msg.c:201) 2 libsystem_kernel.dylib 0x00000001fe64ee2c mach_msg_overwrite + 540 (mach_msg.c:0) 3 libsystem_kernel.dylib 0x00000001fe63c1c8 mach_msg + 24 (mach_msg.c:323) 4 CoreFoundation 0x00000001bf748024 __CFRunLoopServiceMachPort + 160 (CFRunLoop.c:2622) 5 CoreFoundation 0x00000001bf749250 __CFRunLoopRun + 1208 (CFRunLoop.c:3005) 6 CoreFoundation 0x00000001bf74e3ec CFRunLoopRunSpecific + 612 (CFRunLoop.c:3418) 7 GraphicsServices 0x00000001fac1335c GSEventRunModal + 164 (GSEvent.c:2196) 8 UIKitCore 0x00000001c1adb6e8 -[UIApplication _run] + 888 (UIApplication.m:3782) 9 UIKitCore 0x00000001c1adb34c UIApplicationMain + 340 (UIApplication.m:5372) 10 shandongMarket 0x000000010443ab90 main + 80 (main.m:14) 11 dyld 0x00000001dec4edec start + 2220 (dyldMain.cpp:1165) Thread 1 name: Thread 1: 0 libsystem_kernel.dylib 0x00000001fe63c7bc __ulock_wait + 8 1 libdispatch.dylib 0x00000001c6b9f89c _dlock_wait + 56 (lock.c:326) 2 libdispatch.dylib 0x00000001c6b9f650 _dispatch_thread_event_wait_slow + 56 (lock.c:558) 3 libdispatch.dylib 0x00000001c6bae714 __DISPATCH_WAIT_FOR_QUEUE__ + 368 (queue.c:1683) 4 libdispatch.dylib 0x00000001c6bae2c0 _dispatch_sync_f_slow + 148 (queue.c:1769) 5 shandongMarket 0x000000010515ddb4 -[BLYDataManager fetchValueForKey:] + 244 6 shandongMarket 0x00000001051577e4 -[BLYAnalyticsManager lastSessionUseInfo] + 196 7 shandongMarket 0x0000000105157118 -[BLYAnalyticsManager applicationDidCrashed:] + 104 8 CoreFoundation 0x00000001bf706590 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 148 (CFNotificationCenter.c:661) 9 CoreFoundation 0x00000001bf7aa828 ___CFXRegistrationPost_block_invoke + 88 (CFNotificationCenter.c:175) 10 CoreFoundation 0x00000001bf78d8b8 _CFXRegistrationPost + 440 (CFNotificationCenter.c:201) 11 CoreFoundation 0x00000001bf71aafc _CFXNotificationPost + 700 (CFNotificationCenter.c:1193) 12 Foundation 0x00000001b99e5d38 -[NSNotificationCenter postNotificationName:object:userInfo:] + 92 (NSNotification.m:518) 13 shandongMarket 0x0000000105167a18 -[BLYCrashManager didCrashAccidentHappened] + 204 14 shandongMarket 0x000000010513abdc BLYCrashHandlerCallback + 428 15 shandongMarket 0x0000000105138798 BLYBSDSignalHandlerCallback + 96 16 libsystem_platform.dylib 0x000000021f3eb214 _sigtramp + 56 (sigtramp.c:116) 17 libdispatch.dylib 0x00000001c6ba53d8 _dispatch_lane_class_dispose + 172 (queue.c:0) 18 libdispatch.dylib 0x00000001c6b9dd28 _dispatch_dispose + 208 (object.c:257) 19 libdispatch.dylib 0x00000001c6b9e650 -[OS_dispatch_queue _xref_dispose] + 56 (object.m:324) 20 HelpDesk 0x0000000106bf0c18 -[HDFMDatabaseQueue dealloc] + 36 (HDFMDatabaseQueue.m:137) 21 HelpDesk 0x0000000106ba6608 -[FLDBManager closeDB] + 80 (FLDBManager.m:105) 22 HelpDesk 0x0000000106c08b60 -[HDClient closeDB] + 40 (HDClient.m:1112) 23 HelpDesk 0x0000000106c08300 -[HDClient logout:] + 132 (HDClient.m:964) 24 HelpDesk 0x0000000106c08418 __30-[HDClient logout:completion:]_block_invoke + 32 (HDClient.m:974) 25 libdispatch.dylib 0x00000001c6b9d320 _dispatch_call_block_and_release + 32 (init.c:1518) 26 libdispatch.dylib 0x00000001c6b9eeac _dispatch_client_callout + 20 (object.m:560) 27 libdispatch.dylib 0x00000001c6ba1f8c _dispatch_queue_override_invoke + 788 (queue.c:4882) 28 libdispatch.dylib 0x00000001c6bb0944 _dispatch_root_queue_drain + 396 (queue.c:7051) 29 libdispatch.dylib 0x00000001c6bb1158 _dispatch_worker_thread2 + 164 (queue.c:7119) 30 libsystem_pthread.dylib 0x000000021f480da0 _pthread_wqthread + 228 (pthread.c:2631) 31 libsystem_pthread.dylib 0x000000021f480b7c start_wqthread + 8 (:-1)
最新发布
08-07
在iOS应用崩溃日志分析中,`mach_msg2_trap` 和 `__ulock_wait` 是常见的崩溃堆栈符号,它们通常与线程阻塞、死锁、资源竞争或系统调用异常有关。这些崩溃可能发生在主线程或后台线程,具体取决于应用的执行上下文。 ### mach_msg2_trap `mach_msg2_trap` 是 Mach 内核消息传递机制的一部分,通常用于线程间通信(IPC)。当应用在等待某个 Mach 消息时,可能会陷入 `mach_msg2_trap` 状态。如果该状态持续时间过长或无法返回,可能导致 Watchdog 超时或主线程卡死,从而引发崩溃。 这种情况常见于: - 应用在主线程中执行了阻塞的 Mach 消息接收操作 - 与系统服务通信时出现延迟或死锁 - 使用 `NSPort` 或 `NSConnection` 等底层 IPC 机制时未正确处理响应 建议检查是否在主线程执行了长时间的同步 IPC 调用,或是否有未处理的 Mach 端口响应。 ### __ulock_wait `__ulock_wait` 是苹果系统中用于线程同步的底层锁机制,通常与 `os_unfair_lock` 或 `pthread_mutex` 相关。该函数用于在等待锁释放时使线程进入休眠状态。如果多个线程竞争同一锁资源,或者锁未被正确释放,可能导致线程陷入死锁状态,从而引发崩溃。 这类崩溃常见于: - 多线程环境下未正确使用锁机制 - 在主线程中等待某个后台线程持有的锁 - 使用 `dispatch_sync` 在主线队列中同步执行任务,导致死锁 应检查代码中是否存在嵌套的 `dispatch_sync` 调用,或是否在主线程中调用同步锁等待。 ### 日志分析要点 1. **线程状态**:查看崩溃日志中涉及的线程是否处于 `blocked` 或 `waiting` 状态,尤其是主线程。 2. **调用堆栈**:分析堆栈中是否出现 `mach_msg2_trap` 或 `__ulock_wait` 之后没有返回的情况。 3. **死锁检测**:确认是否存在多个线程相互等待资源释放的情况。 4. **系统调用**:检查是否在主线程中执行了可能导致阻塞的系统调用。 5. **第三方库**:部分第三方库可能封装了底层线程或锁机制,需确认其版本和使用方式。 ### 示例代码分析 在排查死锁问题时,可以关注如下代码模式: ```objective-c dispatch_queue_t queue = dispatch_queue_create("com.example.queue", DISPATCH_QUEUE_SERIAL); dispatch_sync(queue, ^{ // 同步执行任务 NSLog(@"Start"); dispatch_sync(dispatch_get_main_queue(), ^{ // 在主线程中再次同步执行 NSLog(@"Deadlock here"); }); }); ``` 上述代码在主线程中调用 `dispatch_sync` 到一个串行队列,并在该队列任务中再次同步提交到主线程,将导致死锁。 ### 解决方案 - **避免在主线程中执行同步锁等待或 IPC 调用** - 使用异步方式处理耗时操作,避免阻塞主线程 - 替换不必要的 `dispatch_sync` 调用为 `dispatch_async` - 使用工具如 Xcode 的 Thread Sanitizer 检测线程竞争和死锁问题 - 定期更新第三方库,确保其线程安全性和兼容性
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值