Is it thread-safe to read an instance variable while calling a setter from another thread?

后端 未结 2 976
逝去的感伤
逝去的感伤 2021-01-21 11:29

I have an object with a property:

@interface Car
@property(strong) NSLicensePlate *licensePlate;
@end

I use the property in a method:



        
相关标签:
2条回答
  • 2021-01-21 12:13

    When you define properties, you can set them as atomic (the default) or nonatomic.

    Since you're using the atomic default, you should be fine about thread safety, but that also depends on how you implemented frobnicate, setLicensePlate: and cleanLicensePlate.

    Please refer to this question to get more details about atomic vs nonatomic: What's the difference between the atomic and nonatomic attributes?

    0 讨论(0)
  • 2021-01-21 12:24

    If you want to enjoy the atomic behavior (which is the default behavior that you get because you didn't specify the nonatomic qualifier) of this property, you must use the getter (self.licensePlate or [self licensePlate]), not use the ivar (_licensePlate).

    In general, it's usually prudent to use the getters and setters everywhere except (a) the init method; and (b) and custom accessor methods. The overhead is negligible and you avoid spectrum of potential problems ranging from atomicity, memory semantics, KVO, future-proofing code in case you customize accessor methods at some future date, etc.

    But, assuming you access your property only through the accessor methods (the getters and setters), the atomic qualifier, as described by Programming with Objective-C: Encapsulating Data ensures that the pointer, itself, that you are retrieving/setting is will not be corrupted by another thread:

    [Atomic] means that the synthesized accessors ensure that a value is always fully retrieved by the getter method or fully set via the setter method, even if the accessors are called simultaneously from different threads.

    In answer to your question, if the other thread changes the licensePlate property, while the frobnicate method is running on the other thread, that original object will not be released until that method returns.

    But to be clear, the atomic qualifier does not ensure thread safety. As the above guide goes on to warn us:

    Note: Property atomicity is not synonymous with an object’s thread safety.

    Consider an XYZPerson object in which both a person’s first and last names are changed using atomic accessors from one thread. If another thread accesses both names at the same time, the atomic getter methods will return complete strings (without crashing), but there’s no guarantee that those values will be the right names relative to each other. If the first name is accessed before the change, but the last name is accessed after the change, you’ll end up with an inconsistent, mismatched pair of names.

    This example is quite simple, but the problem of thread safety becomes much more complex when considered across a network of related objects. Thread safety is covered in more detail in Concurrency Programming Guide.

    So, it might be thread-safe to use frobnicate on one thread while doing other stuff on another thread, but it also might not. It depends upon all the different things that can be done with this license plate object. Because the protections offered by atomic are so minimalist, we frequently will employ some synchronization (via GCD serial queue or GCD reader-writer pattern, or via any of the synchronization methods outlined in the Threading Programming Guide: Synchronization such as locks) to coordinate interaction from different threads.

    0 讨论(0)
提交回复
热议问题