Reputation: 1693
The Apple doc says that
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.
My question is what are the potential repercussions of a property getting initialized more than once?
And in case of a property getting initialized more than once, which one of it will be used? How Swift manages them?
I went through some of the answers.
Is it normal that lazy var property is initialized twice?
But they are just saying that lazy properties can get initialized more than once. I want to know what are the repercussions of this.
Thanks in advance.
Upvotes: 2
Views: 395
Reputation: 299275
(See my comment to rmaddy's answer regarding my concern about thread-safety on writing the pointer itself. My gut is that memory corruption is not possible, but that object duplication is. But I can't prove so far from the documentation that memory corruption isn't possible.)
Object duplication is a major concern IMO if the lazy var has reference semantics. Two racing threads can get different instances:
This means that thread 1 and thread 2 have different instances. That definitely could be a problem if they are expecting to have the same instance. If the type has value semantics, then this shouldn't matter (that being the point of value semantics). But if it has reference semantics, then this very likely be a problem.
IMO, lazy
should always be avoided if multi-threaded callers are possible. It throws uncertainty into what thread the object construction will occur on, and the last thing you want in a thread-safe object is uncertainty about what thread code will run on.
Personally I've rarely seen good use cases for lazy
except for where you need to pass self
in the initializer of one of your own properties. (Even then, I typically use !
types rather than lazy
.) In this way, lazy
is really just a kludgy work-around a Swift init headache that I wish we could solve another way, and do away with lazy
, which IMO has the same "doesn't quite deliver what it promises, and so you probably have to write your own version anyway" problem as @atomic
in ObjC.
The concept of "lazy initialization" is only useful if the type in question is both very expensive to construct, and unlikely to ever be used. If the variable is actually used at some point, it's slower and has less deterministic performance to make it lazy, plus it forces you to make it var
when it is most often readonly.
Upvotes: 3
Reputation: 318794
The answer completely depends on the code you have inside the implementation of the lazy property. The biggest problem would arise from any side effects you've put in the code since they might be called more than once.
If all you do is create a self-contained object, initialize it, and return it, then there won't be any issues.
But if also do things like add a view, update an array or other data structure, or modify other properties, then you have an issue if the lazy variable is created more than once since all of those side effects will happen more than once. You end up adding two views or adding two objects to the array, etc.
Ensure that the code in your lazy property only creates and initializes an object and does not perform any other operations. If you do that, then your code won't cause any issues if the lazy property gets created multiple times from multiple threads.
Upvotes: 1