简体   繁体   中英

What are the potential repercussions of a lazy property getting initialised more than once?

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.

(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:

  • Thread 1 begins to initialize (object A)
  • Thread 2 begins to initialize (object B)
  • Thread 1 assigns A to var and returns A to caller
  • Thread 2 assigns B to var and returns B to caller

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM