支持 属性 比 Swift 中的(惰性)更安全吗?

Is backed property safer than (lazy) in Swift?

使用由另一个 属性 支持的计算 属性 是否比在 Swift 中使用 lazy 修饰符更安全?

// method 1: using LAZY variable
lazy var myVar:Int {
    // assume that this calculation takes
    // a lot of time and resources
    return 5
}

现在考虑 Apple Swift 2(预发布)中的以下引述:

NOTE

If a property marked with the lazy modifier is accessed by multiple threads simultaneously and the property has not yet been initialized, there is no guarantee that the property will be initialized only once.

就个人而言,我一直在做我自己的 "lazy" 逻辑,如下所示:

考虑替代方法:

// method 2: using calculated property backed by another property
var myVar:Int? {
    if self._myVar != nil {
        return self._myVar
    }
    let aVar:Int = 5   // assume this is done after exhaustive calcuation
    self._myVar = aVar
    return self._myVar
}

var _myVar:Int? = nil

使用(方法 2),我能保证 "exhaustive calculation" 只会执行一次吗?

您提出的方法 2 不能保证 lazy 不能保证的任何事情。

// method 2: using calculated property backed by another property
var myVar:Int? {
    if self._myVar != nil {
        return self._myVar
    }
    let aVar:Int = 5   // assume this is done after exhaustive calcuation
    self._myVar = aVar
    return self._myVar
}

var _myVar:Int? = nil

此外,它还有一个额外的缺陷,即它是可选的而不是非可选的。作为隐式解包的可选项,这会稍微好一点,所以我们不必不断地解包它。

而且,我们无法设置 myVar。加上 _myVar 应该是私有的。

但问题是您没有锁定初始化代码以进行同步。

假设你有线程A开始访问myVarif self._myVar != nil 检查 returns 为假,所以我们不会返回 self._myVar。现在我们进入穷举计算。

现在,在穷举计算完成之前,线程 B 尝试访问 myVar。因为线程A还没有穷举完,if self._myVar != nil还是returnsfalse,现在线程B做穷举

本质上,这与 lazy 关键字给您带来的问题相同......但是当 lazy 就足够了时,您编写了很多代码来做到这一点。