在Swift中,支持的财产比(懒惰)更安全吗?

时间:2015-07-12 12:22:52

标签: swift lazy-initialization

使用由另一个属性支持的计算属性比在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(预发布)中的以下引用:

  

请注意

     

如果标有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),我能保证"详尽的计算"只会被执行一次?

1 个答案:

答案 0 :(得分:4)

您建议的方法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检查返回false,因此我们不会返回self._myVar。现在我们进入详尽的计算。

现在,在详尽的计算完成之前,线程B尝试访问myVar。由于线程A尚未完成详尽的计算,if self._myVar != nil仍然返回false,现在线程B进行详尽的计算。

基本上,这就是lazy关键字给你的同样问题....但是当lazy已经足够时,你写了很多代码来做到这一点。