I have read some stuff on ios sdk about multithreading, but I still didn't find the answer to the problem:
In the main thread I have a property, the program does some stuff in a thread, where the value of the property is changed, the other thread needs that changed value.
So how can I change the value of a property or a field in one thread, so that it would change for all threads?
Changing a property on a single object changes the value "for all threads" basically. There's no thread-specific copies of objects unless you make them yourself.
For multithreaded programs, the major challenge is making sure two threads aren't trying to access/write the same memory (a property, in your case) at the same time. Easiest way (but not necessarily most efficient, or fool-proof way) to do this for your property in question is to exclude the "nonatomic" attribute from your property declaration.
(EDIT: this assumes you're using #synthesize to implement your properties, and not #dynamic nor have custom overriding getters or setters.)
Multi-threading is a bit of a large topic to cover here, but Apple's documentation is a good place to start for more info: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html
Related
Question
I am working on a project where I am concerned about the thread safety of an object's properties. I know that when a property is an object such as an NSString, I can run into situations where multiple threads are reading and writing simultaneously. In this case you can get a corrupt read and the app will either crash or result in corrupted data.
My question is for primitive value type properties such as BOOLs or NSIntegers. I am wondering if I can get into a similar situation where I read a corrupt value when reading and writing from multiple threads (and the app will crash)? In either case, I am interested in why.
Clarification - 1/13/17
I am mostly interested in if a primitive value type property is differently susceptible to crashing due to multiple threads accessing it at the same time than an object such as NSMutableString, custom created object, etc. In addition, if there is a difference when accessing memory on the stack vs heap relative to multithreading.
Clarification - 12/1/17
Thank you to #Rob for pointing me to the answer here: stackoverflow.com/a/34386935/1271826! This answer has a great example that shows that depending on the type of architecture you are on (32-bit vs 64-bit), you can get an undefined result when using a primitive property.
Although this is a great step towards answering my question, I still wonder two things:
If there is a multithreading difference when accessing a primitive value property on the stack vs heap (as noted in my previous clarification)?
If you restrict a program to running on one architecture, can you still find yourself in an undefended state when access a primitive value property and why?
I should note that here has been a lot of conversation around atomic vs nonatomic in response to this question. Although this is generally an important concept, this question has little to do with preventing undefined multithreading behavior by using the atomic property modifier or any other thread safety approach such as using GCD.
If your primitive value type property is atomic, then you're assured it cannot be corrupted because your reading it from one thread while setting it from another (as long as you only use the accessor methods, and not interact with the backing ivar directly). That's the entire purpose of atomic. And, as you suggest, this only applicable to fundamental data types (or objects that are both immutable and stateless). But in these narrow cases, atomic can be useful.
Having said that, this is a far cry from concluding that the app is thread-safe. It only assures you that the access to that one property is thread-safe. But often thread-safety must be considered within a broader context. (I know you assure us that this is not the case here, but I qualify this for future readers who too quickly jump to the conclusion that atomic is sufficient to achieve thread-safety. It often is not.)
For example, if your NSInteger property is "how many items are in this cache object", then not only must that NSInteger have its access synchronized, but it must be also be synchronized in conjunction with all interactions with the cache object (e.g. the "add item to cache" and "remove item from cache" tasks, too). And, in these cases, since you'll synchronize all interaction with this broader object somehow (e.g. with GCD queue, locks, #synchronized directive, whatever), making the NSInteger property atomic then becomes redundant and therefore modestly less efficient.
Bottom line, in limited situations, atomic can provide thread-safety for fundamental data types, but frequently it is insufficient when viewed in a broader context.
You later say that you don't care about race conditions. For what it's worth, Apple argues that there is no such thing as a benign race. See WWDC 2016 video Thread Sanitizer and Static Analysis (about 14:40 into it).
Anyway, you suggest you are merely concerned whether the value can be corrupted or whether the app will crash:
I am wondering if I can get into a similar situation where I read a corrupt value when reading and writing from multiple threads (and the app will crash)?
The bottom line is that if you're reading from one thread while mutating on another, the behavior is simply undefined. It could vary. You are simply well advised to avoid this scenario.
In practice, it's a function of the target architecture. For example on 64-bit type (e.g. long long) on 32-bit x86 target, you can easily retrieve a corrupt value, where one half of the 64-bit value is set and the other is not. (See https://stackoverflow.com/a/34386935/1271826 for example.) This results in merely non-sensical, invalid numeric values when dealing with primitive types. For pointers to objects, this obviously would have catestrophic implications.
But even if you're in an environment where no problems are manifested, it's an incredibly fragile approach to eschew synchronization to achieve thread-safety. It could easily break when run on new, unanticipated hardware architectures or compiled under different configuration. I'd encourage you to watch that Thread Sanitizer and Static Analysis video for more information.
I have an object with a property:
#interface Car
#property(strong) NSLicensePlate *licensePlate;
#end
I use the property in a method:
- (void) doSomething {
[_licensePlate frobnicate];
}
And the property value can be changed in another method:
- (void) doSomethingElse {
[self setLicensePlate:[_licensePlateDealer cleanLicensePlate]];
}
Now, if the -doSomethingElse method is called from another thread while I access the license plate property using the instance variable (as seen in the -doSomething method), is it possible to get a segfault?
Is it possible that the -setLicensePlate setter releases the value stored in _licensePlate right before I call -frobnicate on it and before a new valid value is assigned? And would it help to call [self licensePlate] instead of using _licensePlate directly?
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.
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?
With regards to atomic property, Apple's documentation has this below:
This 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.
What does "fully retrieved" or "fully set" mean?
Why is "fully retrieved" or "fully set" not enough to guarantee thread safety?
Note: I am aware there are many posts regarding atomicity on SO, please don't tag this as duplicate unless the ticket specifically address the question above. After reading the posts, I still do not fully understand atomic property.
Atomic means that calls to the getter/setter are synchronized. That way if one thread is setting the property at the same time as another thread is getting it, the one getting the property is guaranteed to get a valid return value. Without it being atomic, it would be possible that the getter retrieves a garbage value, or a pointer to an object that is immediately deallocated. When it's atomic, it will also ensure that if two threads try to set it at the same time, one will wait for the other to finish. If it weren't atomic and two threads tried to set it at the same time, you could end up with a garbage value being written, or possibly objects being over/under retained or over/under released.
So basically, if the property is being set, any other calls to set it or get it will wait for the method to return. Same for if the property is being gotten, any other calls to get it or set it will wait until that get finishes.
This is sometimes sufficient for thread safety depending on what it's being used for. But often you want more than this level of synchronization for thread safety. For example if one block of code on a thread gets the value, makes some change to it, and wants to set it again without some other thread changing it in the meantime. You would have to do additional synchronization to make sure that you have a lock on it from before you get it until after you subsequently set it. You would want to do the same if you wanted to get an object and make some changes to that object without another thread trying to make changes at the same time on it.
"Fully set" and "fully retrieved" means the code below will always print "0x11111111" or "0x22222222". It will never print things like "0x11112222" or "0x11221122". Without atomic or some other appropriate thread synchronization, those sorts of partial reads or partial updates are allowed for some data types on some CPU architectures.
// Thread 1
while (true) x = 0x11111111;
// Thread 2
while (true) x = 0x22222222;
// Thread 3
while (true) printf("0x%x\n", x);
It means the value will never be accessed when it's halfway through being written. It will always be one intended value or another, never an incompletely altered bit pattern.
It isn't enough to guarantee thread-safety because ensuring that the value of a variable is either fully written or nor written at all is not enough to make all the code that uses that variable thread-safe. For example, there might be two variables that need to be updated together (the classical example is transferring credits from one account to another), but code in another thread could see one variable with the new value and one with the old.
Very often, you'll need to implement synchronization for whole systems, so the guarantees offered by atomic variables end up almost not mattering a lot of the time.
Most iPhone code examples use the nonatmoc attribute in their properties. Even those that involve [NSThread detachNewThreadSelector:....]. However, is this really an issue if you are not accessing those properties on the separate thread?
If that is the case, how can you be sure nonatomic properties won't be accessed on this different in the future, at which point you may forget those properties are set as nonatomic. This can create difficult bugs.
Besides setting all properties to atomic, which can be impractical in a large app and may introduce new bugs, what is the best approach in this case?
Please note these these questions are specifically for iOS and not Mac in general.
First,know that atomicity by itself does not insure thread safety for your class, it simply generates accessors that will set and get your properties in a thread safe way. This is a subtle distinction. To create thread safe code, you will very likely need to do much more than simply use atomic accessors.
Second, another key point to know is that your accessors can be called from background or foreground threads safely regardless of atomicity. The key here is that they must never be called from two threads simultaneously. Nor can you call the setter from one thread while simultaneously calling the getter from another, etc. How you prevent that simultaneous access depends on what tools you use.
That said, to answer your question, you can't know for sure that your accessors won't be accessed on another thread in the future. This is why thread safety is hard, and a lot of code isn't thread safe. In general, if youre making a framework or library, yeah, you can try to make your code thread safe for the purposes of "defensive programming", or you can leave it non-thread safe. The atomicity of your properties is only a small part of that. Whichever you choose, though, be sure to document it so users of your library don't have to wonder.
My question, in brief: Is there any way to make mutable collection KVO accessors thread-safe with the same lock that the #synthesized methods are locked?
Explanation: I have a controller class which contains a collection (NSMutableArray) of Post objects. These objects are downloaded from a website, and thus the collection changes from time to time. I would like to be able to use key-value observing to observe the array, so that I can keep my interface updated.
My controller has a posts property, declared as follows:
#property (retain) NSMutableArray *posts;
If I call #synthesize in my .m file, it will create the -(NSMutableArray *)posts and -(void)setPosts:(NSMutableArray *)obj methods for me. Further, they will be protected by a lock such that two threads cannot stomp on each other while setting (or getting) the value.
However, in order to be key-value coding compliant for a mutable ordered collection, there are a few other methods I need to implement. Specifically, I need to implement at least the following:
-insertObject:inPostsAtIndex:
-removeObjectFromPostsAtIndex:
However, since the posts are downloaded asynchronously, I would like to be able to insert new posts into the array on a background thread as well. This means that access needs to be thread-safe.
So, my question. Is there any way to make those accessors thread-safe with the same lock that the #synthesized methods are locked? Or do I have to resort to specifying the setPosts: and posts methods myself in order to guarantee full atomicity across all accessors?
The Objective-C docs at developer.apple.com[1] don't state that there's a way to use the same lock for your explicitly defined functions as gets used for your #synthesized functions. In that case I'd say that to be completely safe it would be better to fully define your own functions to be sure they all use the same lock.
You may be able to use the debugger to determine the name of the lock that gets used for your #synthesized functions, but that's not something I'd rely on.
You probably don't really want to do this. If you do succeed, KVO-notifications will be received on the same thread that makes the change, and if it's a background thread, will be unsuitable for updating the UI.
Instead, why not have your background thread update the property using the main thread? Then you don't even need the property to be atomic.