gpt4 book ai didi

swift - 同步调度的保留计数如何工作?

转载 作者:行者123 更新时间:2023-12-03 13:03:06 25 4
gpt4 key购买 nike

我试图解释对象的所有权以及 GCD 是如何工作的。
这些是我学到的东西:

  • 一个函数将增加其针对
  • 调用的对象的保留计数
  • 一个调度 block ,除非它捕获 self弱会增加计数。
  • 在执行调度的 block 后,它会释放捕获的对象,因此保留计数为 self应该减少。但这不是我在这里看到的。这是为什么?


  • class C {
    var name = "Adam"

    func foo () {
    print("inside func before sync", CFGetRetainCount(self)) // 3
    DispatchQueue.global().sync {
    print("inside func inside sync", CFGetRetainCount(self)) // 4
    }
    sleep(2)
    print("inside func after sync", CFGetRetainCount(self)) // 4 ?????? I thought this would go back to 3
    }
    }

    用法:
    var c: C? = C()
    print("before func call", CFGetRetainCount(c)) // 2
    c?.foo()
    print("after func call", CFGetRetainCount(c)) // 2

    最佳答案

    几个想法:

  • 如果您对 ARC 在幕后保留和释放的确切位置有疑问,只需在“同步后内部函数”之后添加断点,运行它,当它停止时使用“调试”»“调试工作流”»“始终显示反汇编”你可以看到程序集,准确地看到发生了什么。我还建议使用发布/优化构建来执行此操作。

    查看程序集,版本在您的 foo 末尾。方法。
  • 正如您所指出的,如果您更改 DispatchQueue.global().sync打电话成为 async ,您会看到预期的行为。

    此外,不出所料,如果您执行功能分解,移动 GCD sync调用一个单独的函数,您将再次看到您所期望的行为。
  • 你说:

    a function will increase the retain count of the object its calling against



    为了澄清发生了什么,我建议您引用 WWDC 2018 What’s New in Swift ,大约 12:43 进入视频,他们在视频中讨论了编译器在哪里插入 retainrelease调用,以及它在 Swift 4.2 中的变化。

    在 Swift 4.1 中,它使用“Owned”调用约定,调用者会在调用函数之前保留对象,而被调用函数负责在返回之前执行释放。

    在 4.2 中(如下面的 WWDC 屏幕快照所示),他们实现了“保证”调用约定,消除了许多多余的保留和释放调用:

    enter image description here

    这至少在优化的构建中导致更高效和更紧凑的代码。所以,做一个发布构建并查看程序集,你会看到它在起作用。
  • 现在,我们来到您问题的根源,为什么 GCD sync函数的行为与其他场景不同(例如,它的释放调用插入到与其他具有非转义闭包的场景不同的位置)。

    似乎这可能与 GCD 独有的优化有关 sync .具体来说,当您同步调度到某个后台队列时,而不是停止当前线程,然后在指定队列的工作线程之一上运行代码,编译器足够聪明地确定当前线程将处于空闲状态并且它将如果可以的话,只需在当前线程上运行分派(dispatch)的代码。我很容易想象这个 GCD sync优化,可能会在关于编译器在何处插入发布调用的逻辑中引入皱纹。

  • 恕我直言,发布是在方法结束而不是在关闭结束时完成的事实有点学术问题。我假设他们有充分的理由(或至少是实际的理由),将其推迟到函数的末尾。重要的是当您从 foo 返回时,保留计数是应该的。

    关于swift - 同步调度的保留计数如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58378448/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com