【问题标题】:iOS get stuck in instantiation dependency without failingiOS陷入实例化依赖而没有失败
【发布时间】:2023-03-17 16:36:01
【问题描述】:

如果我有类似的东西

class Foo {
  static shared = Foo()
  init() {
    print("init Foo")
    let _ = Bar.shared
  }
}

class Bar {
  static shared = Bar()
  init() {
    print("init Bar")
    let _ = Foo.shared
  }
}

// somwehere else:
let _ = Foo.shared

然后应用程序卡住了。什么都没发生。我知道这种设计是错误的,但我想知道为什么应用程序没有崩溃、报告错误或至少打印一个循环。以上代码打印

init Foo
init Bar

就是这样,表明它不是循环,而是卡住了。想知道发生了什么?

【问题讨论】:

    标签: swift instantiation static-variables


    【解决方案1】:

    在 Swift 中,静态类型属性以保证线程安全的方式延迟初始化。

    注意Type Properties

    存储类型属性在首次访问时被延迟初始化。 它们保证只被初始化一次,即使被 多个线程同时进行,不需要标记 使用惰性修饰符。

    这个只有一次功能利用了dispatch_once-like 需要互斥的东西(或者完全是它自己)。

    初始化Foo.shared 时,Foo.shared 的锁被锁定。而当它被锁定时,Bar.shared 需要被初始化,所以Bar.shared 的锁被锁定。虽然两者都被锁定,Foo.shared 需要初始化,但它的锁已经被锁定,所以等到锁被释放...

    我们称这种情况为死锁

    【讨论】:

    • 锁定是有道理的。对于这种死锁情况,应用程序是否没有显示错误或不会崩溃?应用程序是否甚至知道存在死锁,或者它只是没有看到它并等待事情解决?对我来说,这听起来很像一个应该报告的错误并大声失败
    • @Guig,一般的死锁检测有点困难,但是,是的,在一些典型和简单的情况下,可以在编译时检测到死锁,并且某种调试运行时会能够在运行时检测死锁。也许这些功能“还没有”或优先级较低。您可以通过Apple's Bug Reporter 编写功能请求。如果没有这些功能,应用程序将永远等待......
    猜你喜欢
    • 1970-01-01
    • 2019-06-16
    • 2017-09-16
    • 1970-01-01
    • 2014-02-28
    • 2019-11-23
    • 2012-08-13
    • 2017-09-24
    • 1970-01-01
    相关资源
    最近更新 更多