• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - 单线程调用两次performBlockAndWait是否会导致死锁?

[复制链接]
菜鸟教程小白 发表于 2022-12-12 10:40:50 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我在performBlockAndWait 文档中发现了类似这样的内容:

This method may safely be called reentrantly.

我的问题是这是否意味着它永远不会导致死锁,例如会像在单个上下文中那样调用它吗?:

NSManageObjectContext *context = ...

[context performBlockAndWait:^{
       // ... some stuff

       [context performBlockAndWait:^{

       }];
 }];



Best Answer-推荐答案


您可以使用一小段代码自行尝试 ;)

但确实,它不会死锁。

我怀疑,内部实现使用队列特定 token 来识别代码执行的当前队列(参见 dispatch_queue_set_specificdispatch_queue_get_specific)。

如果它确定当前正在执行的代码在它自己的私有(private)队列或子队列上执行,它会简单地绕过同步提交 block ——这会导致死锁,而是直接执行它。

一个可能的实现如下所示:

func executeSyncSafe(f: () -> ()) {
    if isSynchronized() {
        f()
    } else {
        dispatch_sync(syncQueue, f)
    }
}

func isSynchronized() -> Bool {
    let context = UnsafeMutablePointer<Void>(Unmanaged<dispatch_queue_t>.passUnretained(syncQueue).toOpaque())
    return dispatch_get_specific(&queueIDKey) == context 
}

队列可以这样创建:

private var queueIDKey = 0  // global


init() {
    dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
            QOS_CLASS_USER_INTERACTIVE, 0))
    let context = UnsafeMutablePointer<Void>(Unmanaged<dispatch_queue_t>.passUnretained(syncQueue).toOpaque())
    dispatch_queue_set_specific(syncQueue, &queueIDKey, context, nil)
}

dispatch_queue_set_specific 将一个token(这里是context - 它只是队列的指针值)与某个key 该队列。稍后,您可以尝试为指定 key 的任何队列检索该 token ,并检查当前队列是同一队列还是子队列。如果是这样,则绕过对队列的调度,而是直接调用函数 f

关于ios - 单线程调用两次performBlockAndWait是否会导致死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35577556/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap