苹果医生说
如果标有lazy修饰符的属性被多个访问 同时执行线程,并且该属性尚未初始化, 无法保证该属性只能被初始化一次。
我的问题是,一次多次初始化属性的潜在影响是什么?
并且如果一个属性被多次初始化,将使用哪个属性? Swift如何管理它们?
我回答了一些答案。
Is it normal that lazy var property is initialized twice?
但是他们只是说懒属性可以被初始化多次。我想知道这有什么影响。
谢谢。
答案 0 :(得分:3)
(请参阅我对rmaddy的回答的评论,该评论涉及我对编写指针本身的线程安全性的关注。我的直觉是不可能发生内存损坏,但对象重复是可能的。但是我无法证明与文档相距甚远内存损坏是不可能的。)
如果惰性变量具有引用语义,则对象复制是IMO的主要问题。两个竞速线程可以获取不同的实例:
这意味着线程1和线程2具有不同的实例。如果他们期望拥有相同的实例,那肯定是一个问题。如果类型具有值语义,则这无关紧要(这是值语义的关键)。但是,如果它具有引用语义,那么这很可能是一个问题。
IMO,lazy
应该始终避免,如果可能的话,多线程调用程序是可以避免的。它将不确定对象构造将在哪个线程上发生,而线程安全对象中的最后一件事就是不确定将在哪个线程上运行代码。
我个人很少见到lazy
的好用例,除了您需要在自己的属性之一的初始化程序中传递self
的地方。 (即使那样,我通常也使用!
类型而不是lazy
。)这样,lazy
确实是个繁琐的工作,解决了Swift init头疼的问题,我希望我们能解决另一个问题方式,并消除lazy
,这与IMO同样具有“不能完全兑现所承诺的,因此您可能仍然必须编写自己的版本”问题,如ObjC中的@atomic
。< / p>
“惰性初始化”的概念仅在所讨论的类型构造起来非常昂贵且不太可能使用 时才有用。如果实际在某个时候使用了该变量,则它变慢并且确定性的性能降低,使其变得懒惰,此外,它迫使您将其设置为var
,而该变量通常是只读的。
答案 1 :(得分:1)
答案完全取决于您在lazy属性的实现内部具有的代码。最大的问题可能是由于您在代码中添加了任何副作用,因为它们可能会被多次调用。
如果您要做的只是创建一个自包含的对象,将其初始化并返回,则不会有任何问题。
但是,如果还执行添加视图,更新数组或其他数据结构或修改其他属性的操作,那么如果多次创建惰性变量,就会遇到问题,因为所有这些副作用都会发生一旦。您最终将添加两个视图或将两个对象添加到数组等。
确保您的lazy属性中的代码仅创建和初始化一个对象,并且不执行任何其他操作。如果这样做,那么如果从多个线程多次创建lazy属性,那么您的代码将不会引起任何问题。