A class of service has a nonatomic property which is set in a serial queue.
#interface Service
#property (strong, nonatomic) NSDictionary *status;
#property (nonatomic) dispatch_queue_t queue;
...
#end
- (void)update:(NSDicationary *)paramDict {
dispatch_async(self.queue, ^{
....
self.status = updateDict;
}
}
- (void)someMethod {
NSDictionary *status = self.status;
}
The app crashed when the getter was invoked, at objc_autorelease + 6, which seems to be a runtime/Clang/llvm invocation.
And the crash log also showed that the status property was just set on the queue thread.
Did it crash because of the lack of atomicity in the accessors? If yes, how and why the getter failed retaining the instance? Did the autorelease pool get drained inside the synthesized nonatomic setter?
Should I implement the getter/setter method, protecting it with queue/a mutex lock?
While atomic can address some integrity issues of fundamental data types in multi-threaded code, it's not sufficient to achieve thread-safety in general. Thread-safety is generally achieved through the judicious use of locks or queues. See the Synchronization section of the Threading Programming Guide. Or see Eliminating Lock-Based Code of the Concurrency Programming Guide that describes the use of queues in lieu of synchronization locks.
Assuming your queue is serial, you might be able to make it thread-safe by using the following construct:
- (void)someMethod {
dispatch_sync(self.queue, ^{
NSDictionary *status = self.status;
// do what you need to with status
});
}
That way, you're effectively using your serial queue to synchronize access to the status dictionary.
By the way, if your queue is a custom concurrent, you might also want to make sure that you replace the dispatch_async in paramDict to be dispatch_barrier_async. If your queue is serial, then dispatch_async is fine.
I'd suggest you try synchronizing your access to status, either using your queue or one of the synchronization techniques described in the Threading Programming Guide.
If you don't mind, change the code like this.
nonatomic -> atomic
Related
Apple provides some documentation about synchronizing variables and even order of execution. What I don't see is any documentation on CPU cache behavior. What guarantees and control does the Objective-C developer have to ensure cache coherence between threads?
Consider the following where a variable is set on a background thread but read on the main thread:
self.count = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
self.count = 5;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"%i", self.count);
});
}
Should count be volatile in this case?
Update 1
The documentation in Inter-thread Communication guarantees that shared variables can be used for inter-thread communication.
Another simple way to communicate information between two threads is to use a global variable, shared object, or shared block of memory.
Does this imply volatile is not required in this case? This is conflicting with the documentation in Memory Barriers and Volatile Variables:
If the variable is visible from another thread however, such an optimization might prevent the other thread from noticing any changes to it. Applying the volatile keyword to a variable forces the compiler to load that variable from memory each time it is used.
So I still don't know whether volatile is required because the compiler could use register caching optimizations or if it's not required because the compiler somehow knows it's a "shared" something.
The documentation is not very clear about what a shared variable is or how the compiler knows about it. In the above example, is count a shared object? Let's say count is an int, then it's not an object. Is it a shared block of memory or does that only apply to __block declared variables? Maybe volatile is required for non-block, non-object, non-global, shared variables.
Update 2
To everyone thinking this is a question about synchronization, it's not. This is about CPU cache behavior on the iOS platform.
I know you are probably asking about the general case of using variables across threads (in which case the rules about using volatile and locks are the same for ObjC as it is for normal C). However, for the example code you posted the rules are a little different. (I'll be skipping over and simplifying things and using Xcode to mean both Xcode and the compiler)
self.count = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
self.count = 5;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"%i", self.count);
});
}
I'm going to assume self is an NSObject subclass something like this:
#interface MyClass : NSObject {
NSInteger something;
}
#property (nonatomic, assign) NSInteger count;
#end
Objective C is a superset of C, and if you've ever done any reverse engineering of ObjC you'll know that ObjC code (sort of, not quite) gets converted into C code before it's compiled. All [self method:object] calls get converted to objc_msgSend(self, "method:", object) calls and self is a C struct with ivars and other runtime info in it.
This means this code doesn't do quite what you might expect.
-(void)doThing{
NSInteger results = something + self.count;
}
Just accessing something isn't just accessing the variable but is instead doing self->something (which is why you need to get a weak reference to self when accessing an ivar in an Objective C block to avoid a retain cycle).
The second point is Objective C properties don't really exist. self.count gets turned into [self count] and self.count = 5 gets turned into [self setCount:5]. Objective C properties are just syntax sugar; convenience save you some typing and make things look a bit nicer.
If you've been using Objective C for more than a few years ago you'll remember when you had to add #synthesize propertyName = _ivarName to the #implementation for ObjC properties you declared in the header. (now Xcode does it automatically for you)
#synthesize was a trigger for Xcode to generate the setter and getter methods for you. (if you hadn't written #synthesize Xcode expected you to write the setter and getter yourself)
// Auto generated code you never see unless you reverse engineer the compiled binary
-(void)setCount:(NSInteger)count{
_count = count;
}
-(NSInteger)count{
return _count;
}
If you are worried about threading issues with self.count you are worried about 2 threads calling these methods at once (not directly accessing the same variable at once, as self.count is actually a method call not a variable).
The property definition in the header changes what code is generated (unless you implement the setter yourself).
#property (nonatomic, retain)
[_count release];
[count retain];
_count = count;
#property (nonatomic, copy)
[_count release];
_count = [count copy];
#property (nonatomic, assign)
_count = count;
TLDR
If you care about threading and want to make sure you don't read the value half way through a write happening on another thread then change nonatomic to atomic (or get rid of nonatomic as atomic is the default). Which will result in code generated something like this.
#property (atomic, assign) NSInteger count;
// setter
#synchronized(self) {
_count = count;
}
This won't guarantee your code is thread safe, but (as long as you only access the property view it's setter and getter) should mean you avoid the possibility of reading the value during a write on another thread. More info about atomic and nonatmoic in the answers to this question.
The simplest way, and the way that is least challenging to the developer's brain, is to perform tasks on a serial dispatch queue. A serial dispatch queue, like the main queue, is a tiny single threaded island in a multi-threaded world.
You should use lock or some other synchronise mechanism to protect the shared variable. According to the documentation it said:
Another simple way to communicate information between two threads is to use a global variable, shared object, or shared block of memory. Although shared variables are fast and simple, they are also more fragile than direct messaging. Shared variables must be carefully protected with locks or other synchronization mechanisms to ensure the correctness of your code. Failure to do so could lead to race conditions, corrupted data, or crashes.
In fact the best way to protect the counter variable is to use the Atomic Operation. You can read the article: https://www.mikeash.com/pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html
Typically #synchronized(self) creates something like critical section.
My problem is I have more than one function which should be accessed with one thread only.
But what will the application do if I write #synchronized(self) in each such method? Does it mean one thread can use method1 and other thread can use method2? If no then how to implement it correctly?
#synchronized attempts to obtain a lock on the object that is passed to it. If the lock is obtained then execution continues. If the lock can't be contained then the thread blocks until the lock can be obtained.
The object that you pass to #synchronized should be the object that you want to protect from simultaneous updates. This may be self or it may be a property of self. For example, consider the following simple queue implementation:
#property (nonatomic,strong) NSMutableArray *qArray;
-(void)append:(id)newObject {
#synchronized(self.qArray) {
[self.qArray addObject:newObject];
}
}
-(id) head {
id ret=nil;
#synchronized(self.qArray) {
if (self.qArray.count >0) {
ret=self.qArray[0];
[self.qArray removeObjectAtIndex:0];
}
}
return ret;
}
In this case self.qArray is a good choice for the #synchronized as it is the object being modified
Frome someone
The object passed to the #synchronized directive is a unique identifier used to distinguish the protected block. If you execute the preceding method in two different threads, passing a different object for the anObj parameter on each thread, each would take its lock and continue processing without being blocked by the other. If you pass the same object in both cases, however, one of the threads would acquire the lock first and the other would block until the first thread completed the critical section.
- (void)myMethod:(id)anObj
{
#synchronized(anObj)
{
// Everything between the braces is protected by the #synchronized directive.
}
}
If you access two (or more) functions via one thread. the #synchronized would don't affect your code. because your function is run synchronised without lock help.
Does Option #1 below run some sort of implied queue? It does not seem to run on the main queue because when I tried to update UI stuff there it complained until I moved to Option #3 so I’m assuming that blocks have their own queue or thread? Before it complained I was under the impression if I didn’t start a dispatch queue that things would just run like normal, which in my mind would be on the main queue. Here’s some example code to illustrate:
// UserViewController.h
#interface UserViewController : NSObject
#property(nonatomic, strong) Server *server;
#property(nonatomic, strong) User *user;
#end
// UserViewController.m - Controller that sets a block for use in another class
#implementation UserViewController
- (void)doSomething {
// I'd like to call other methods and set #properties from the controller and I've heard
// __weak is the correct keyword to use (rather than __block or __strong).
__weak UserViewController *weakController = self;
// Option #0 - Outside of block
weakController.user = [[RHZUser alloc] init];
server.callbackBlock = ^(NSURLResponse *response, NSData *data, NSError *error) {
// Option #1 - Outside of dispatch queues. Is this in some sort of default queue?
weakController.user = [[RHZUser alloc] init];
dispatch_queue_t backgroundQueue
= dispatch_queue_create("com.example.backgroundQueue", nil);
dispatch_async(backgroundQueue, ^{
// Option #2 - This is on the serial queue I created
weakController.user = [[RHZUser alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
// Option #3 - The main queue where all my UI is
weakController.user = [[RHZUser alloc] init];
} // dispatch_async
} // dispatch_async
}; // self.callbackBlock
}
#end
// Server.m - Class that uses the block defined in the controller
#implementation Server
- makeAServerCall {
[NSURLConnection sendAsynchronousRequest:
[NSMutableURLRequest requestWithURL:restServiceURL]
queue:[[NSOperationQueue alloc] init]
completionHandler:self.callbackBlock];
}
#end
A block is a piece of code that, when executed, runs on a particular queue. Setting a block on some object does not make it run, nor does it get attached to one particular queue.
In the case of option 1, you set a block property on an instance of Server. This does not mean it's run, all it does is make that code accessible to anyone that has access to that block. Because the name of the property is callbackBlock, I'll assume that the Server instance executes the block when it finishes something.
That's when the block gets tied to a queue. Server's implementation decides whether it runs on the main queue or not, and should document (probably in its .h) whether it does or not. If it's not documented, but I absolutely need it run on the main queue, I always play it safe and make sure it gets called on the main thread by wrapping it in a dispatch_async.
EDIT:
Assuming your Server implementation is the same as Server's, you create a new queue using alloc/init and pass that to NSURLConnection. From the NSURLConnection documentation:
queue
The operation queue to which the handler block is dispatched when the request completes or failed.
So, the behavior is indeed documented and if you want the handler to be called on the main queue, simply pass dispatch_get_main_queue.
You can just call a block. Same as a call using a function pointer; actually the same syntax as using a function pointer. That block will just run on the same thread as the caller.
dispatch_block_t myBlock = ^ { NSLog (#"This is a block!"); };
myBlock ();
prints "This is a block!" on the same thread that the code is running on. callbacks will run on whatever thread they have been called on. So your "Option 1" block is performed on whatever queue the caller of that block decided to perform it on. Usually this should be documented by the method using the callback. There are some methods using callbacks that allow you to pass in a queue, and they will dispatch the callback on that queue.
Blocks are just things that you can call like a function. They do not care about or do anything with threads and queues per se. Your question would be exactly the same if you had asked "Using Grand Central Dispatch on iOS, what queue (if any) do regular C functions run on if they are not in a dispatch queue?" or "Using Grand Central Dispatch on iOS, what queue (if any) do regular Objective-C methods run on if they are not in a dispatch queue?" The answer to that would be the answer to the title of this question.
So what's the answer to those questions? Well, a function (or a method, or a block) runs when you call it. It's that simple. So by definition it runs on whatever thread or queue you were in when you call it. So what thread then code in your block runs in depends on what thread the code that calls it is in. So how is the block called? The block is passed to +[NSURLConnection sendAsynchronousRequest:queue:completionHandler:];, and it is that code that somehow calls it. We don't have the code of that library, but its documentation says that the completion handler is executed in the NSOperationQueue passed in as the second argument. You pass a new NSOperationQueue object as the second argument.
An NSOperationQueue maintains an internal thread or dispatch queue on which the operations are run. You don't have access to and should not care about this internal queue; you just know that the operations are executed on something that is separate from the other queues and threads, so is definitely not the main thread.
Its possible that Server has incorrectly (in my opinion) implemented their call back blocks on a queue that is not the main queue. You can check if option #1 is definitely not on the main queue by checking [NSThread isMainThread];. You usually only change UIKit elements on the main thread (there are some exceptions - as always!).
Usually web service callback (or completion) blocks are sent back to the main thread as is the case for AFNetworking for example.
We created an operation framework to add some functionality not found in the base classes (e.g. tracking success/failure). Parent operations are usually non-concurrent, and may only exist to manage child operations. Child operations which are typically concurrent (downloading xml and media asynchronously).
When we run our application on iOS 7, add we a number of operations to the operation queue, ~3/4 of the operations complete, and then the app appears to hang.
When I pause the app in the debugger, and I examine the operations in the queue (sOpQueue.operations), many of them are ready to run (isReady returns TRUE), but apparently none of them are executing (isExecuting returns FALSE, and I see no evidence of any operation running on any thread).
This is a new problem as of iOS 7.
The behavior does not seem to change when I increase or decrease the number of concurrent operations.
Does anyone have any suggestions on how to determine why a ready operation is not being started?
Thanks,
Chuck
Are you issuing the isReady Key Value Observing notification?
For example, I use a property:
#property (nonatomic, getter = isReady) BOOL ready;
And then have a custom setter:
- (void)setReady:(BOOL)ready
{
[self willChangeValueForKey:#"isReady"];
_ready = ready;
[self didChangeValueForKey:#"isReady"];
}
As well as a custom getter that calls super:
- (BOOL)isReady
{
return _ready && [super isReady];
}
And, because you implemented both the setter and getter, you have to manually synthesize the property at the beginning of the #implementation (usually you don't have to do this anymore, but if you implement all of the custom accessors, you have to manually #synthesize):
#synthesize ready = _ready;
Then, the operation starts when both of the following conditions are satisfied:
The ready property is set to YES (note, use the setter, not the ivar directly);
self.ready = YES;
or
[self setReady:YES];
All other standard NSOperation criteria are satisfied (e.g. dependencies between operations, honoring maxConcurrentOperationCount, factoring in priorities, etc.).
I'll bet you have concurrent operations that haven't finished properly. Raise you number of concurrent operations and see if you can run longer before it hangs. Then figure out why your concurrent operations aren't correctly setting isFinished.
With reference to this answer, I am wondering is this correct?
#synchronized does not make any code "thread-safe"
As I tried to find any documentation or link to support this statement, for no success.
Any comments and/or answers will be appreciated on this.
For better thread safety we can go for other tools, this is known to me.
#synchronized does make code thread safe if it is used properly.
For example:
Lets say I have a class that accesses a non thread safe database. I don't want to read and write to the database at the same time as this will likely result in a crash.
So lets say I have two methods. storeData: and readData on a singleton class called LocalStore.
- (void)storeData:(NSData *)data
{
[self writeDataToDisk:data];
}
- (NSData *)readData
{
return [self readDataFromDisk];
}
Now If I were to dispatch each of these methods onto their own thread like so:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[LocalStore sharedStore] storeData:data];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[LocalStore sharedStore] readData];
});
Chances are we would get a crash. However if we change our storeData and readData methods to use #synchronized
- (void)storeData:(NSData *)data
{
#synchronized(self) {
[self writeDataToDisk:data];
}
}
- (NSData *)readData
{
#synchronized(self) {
return [self readDataFromDisk];
}
}
Now this code would be thread safe. It is important to note that if I remove one of the #synchronized statements however the code would no longer be thread safe. Or if I were to synchronize different objects instead of self.
#synchronized creates a mutex lock on the object you are syncrhonizing. So in other words if any code wants to access code in a #synchronized(self) { } block it will have to get in line behind all previous code running within in that same block.
If we were to create different localStore objects, the #synchronized(self) would only lock down each object individually. Does that make sense?
Think of it like this. You have a whole bunch of people waiting in separate lines, each line is numbered 1-10. You can choose what line you want each person to wait in (by synchronizing on a per line basis), or if you don't use #synchronized you can jump straight to the front and skip all the lines. A person in line 1 doesn't have to wait for a person in line 2 to finish, but the person in line 1 does have to wait for everyone in front of them in their line to finish.
I think the essence of the question is:
is the proper use of synchronize able to solve any thread-safe
problem?
Technically yes, but in practice it's advisable to learn and use other tools.
I'll answer without assuming previous knowledge.
Correct code is code that conforms to its specification. A good specification defines
invariants constraining the state,
preconditions and postconditions describing the effects of the operations.
Thread-safe code is code that remains correct when executed by multiple threads. Thus,
No sequence of operations can violate the specification.1
Invariants and conditions will hold during multithread execution without requiring additional synchronization by the client2.
The high level takeaway point is: thread-safe requires that the specification holds true during multithread execution. To actually code this, we have to do just one thing: regulate the access to mutable shared state3. And there are three ways to do it:
Prevent the access.
Make the state immutable.
Synchronize the access.
The first two are simple. The third one requires preventing the following thread-safety problems:
liveness
deadlock: two threads block permanently waiting for each other to release a needed resource.
livelock: a thread is busy working but it's unable to make any progress.
starvation: a thread is perpetually denied access to resources it needs in order to make progress.
safe publication: both the reference and the state of the published object must be made visible to other threads at the same time.
race conditions A race condition is a defect where the output is dependent on the timing of uncontrollable events. In other words, a race condition happens when getting the right answer relies on lucky timing. Any compound operation can suffer a race condition, example: “check-then-act”, “put-if-absent”. An example problem would be if (counter) counter--;, and one of several solutions would be #synchronize(self){ if (counter) counter--;}.
To solve these problems we use tools like #synchronize, volatile, memory barriers, atomic operations, specific locks, queues, and synchronizers (semaphores, barriers).
And going back to the question:
is the proper use of #synchronize able to solve any thread-safe
problem?
Technically yes, because any tool mentioned above can be emulated with #synchronize. But it would result in poor performance and increase the chance of liveness related problems. Instead, you need to use the appropriate tool for each situation. Example:
counter++; // wrong, compound operation (fetch,++,set)
#synchronize(self){ counter++; } // correct but slow, thread contention
OSAtomicIncrement32(&count); // correct and fast, lockless atomic hw op
In the case of the linked question you could indeed use #synchronize, or a GCD read-write lock, or create a collection with lock stripping, or whatever the situation calls for. The right answer depend on the usage pattern. Any way you do it, you should document in your class what thread-safe guarantees are you offering.
1 That is, see the object on an invalid state or violate the pre/post conditions.
2 For example, if thread A iterates a collection X, and thread B removes an element, execution crashes. This is non thread-safe because the client will have to synchronize on the intrinsic lock of X (synchronize(X)) to have exclusive access. However, if the iterator returns a copy of the collection, the collection becomes thread-safe.
3 Immutable shared state, or mutable non shared objects are always thread-safe.
Generally, #synchronized guarantees thread safety, but only when used correctly. It is also safe to acquire the lock recursively, albeit with limitations I detail in my answer here.
There are several common ways to use #synchronized wrong. These are the most common:
Using #synchronized to ensure atomic object creation.
- (NSObject *)foo {
#synchronized(_foo) {
if (!_foo) {
_foo = [[NSObject alloc] init];
}
return _foo;
}
}
Because _foo will be nil when the lock is first acquired, no locking will occur and multiple threads can potentially create their own _foo before the first completes.
Using #synchronized to lock on a new object each time.
- (void)foo {
#synchronized([[NSObject alloc] init]) {
[self bar];
}
}
I've seen this code quite a bit, as well as the C# equivalent lock(new object()) {..}. Since it attempts to lock on a new object each time, it will always be allowed into the critical section of code. This is not some kind of code magic. It does absolutely nothing to ensure thread safety.
Lastly, locking on self.
- (void)foo {
#synchronized(self) {
[self bar];
}
}
While not by itself a problem, if your code uses any external code or is itself a library, it can be an issue. While internally the object is known as self, it externally has a variable name. If the external code calls #synchronized(_yourObject) {...} and you call #synchronized(self) {...}, you may find yourself in deadlock. It is best to create an internal object to lock upon that is not exposed outside of your object. Adding _lockObject = [[NSObject alloc] init]; inside your init function is cheap, easy, and safe.
EDIT:
I still get asked questions about this post, so here is an example of why it is a bad idea to use #synchronized(self) in practice.
#interface Foo : NSObject
- (void)doSomething;
#end
#implementation Foo
- (void)doSomething {
sleep(1);
#synchronized(self) {
NSLog(#"Critical Section.");
}
}
// Elsewhere in your code
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
Foo *foo = [[Foo alloc] init];
NSObject *lock = [[NSObject alloc] init];
dispatch_async(queue, ^{
for (int i=0; i<100; i++) {
#synchronized(lock) {
[foo doSomething];
}
NSLog(#"Background pass %d complete.", i);
}
});
for (int i=0; i<100; i++) {
#synchronized(foo) {
#synchronized(lock) {
[foo doSomething];
}
}
NSLog(#"Foreground pass %d complete.", i);
}
It should be obvious to see why this happens. Locking on foo and lock are called in different orders on the foreground VS background threads. It's easy to say that this is bad practice, but if Foo is a library, the user is unlikely to know that the code contains a lock.
#synchronized alone doesn't make code thread safe but it is one of the tools used in writing thread safe code.
With multi-threaded programs, it's often the case of a complex structure that you want to be maintained in a consistent state and you want only one thread to have access at a time. The common pattern is to use a mutex to protect a critical section of code where the structure is accessed and/or modified.
#synchronized is thread safe mechanism. Piece of code written inside this function becomes the part of critical section, to which only one thread can execute at a time.
#synchronize applies the lock implicitly whereas NSLock applies it explicitly.
It only assures the thread safety, not guarantees that. What I mean is you hire an expert driver for you car, still it doesn't guarantees car wont meet an accident. However probability remains the slightest.
It's companion in GCD(grand central dispatch) is dispatch_once. dispatch_once does the same work as to #synchronized.
The #synchronized directive is a convenient way to create mutex locks on the fly in Objective-C code.
side-effects of mutex locks:
deadlocks
starvation
Thread safety will depend on usage of #synchronized block.