views:

632

answers:

2

Hi there,

I have a block of code that is accessed frequently and from either the main thread or several other background threads. I need to ensure that this code only gets processed one at a time.

I'm currently using a @synchronized(self) { } block but I'm not sure if that's providing the correct protection. How does it differ from an NSLock instance?

Finally, can anyone suggest how I can protect my method? The method is in my application delegate, and I access it from various threads by calling:

[[[UIApplication sharedApplication] delegate] myMethod];

Many thanks,

Mike

+5  A: 

There is a great Blog post on the Google Mac blog about the inner workings of @synchronized:
http://googlemac.blogspot.com/2006/10/synchronized-swimming.html

I'm currently using a @synchronized(self) { } block but I'm not sure if that's providing the correct protection. How does it differ from an NSLock instance?

There are several ways to synchronize critical sections (@synchronized, NSLock, OSSpinLoc, ...).
I think @synchronized is the most convenient (and also the slowest) approach.
Here is a good SO answer that explains the differences between @synchronized and NSLock.

You are accessing your method over a shared instances (which basically is a singleton) delegate. Maybe you can rethink your design and figure out a way that allows you to lock a smaller piece of code within myMethod.

weichsel
Thanks for your help! Is it correct to always use `self`? Self in this case will point to the application delegate, no matter what's calling it? I'm confused as to why you have to pass something into it!
Michael Waterfall
You use (self) if you want to lock "per instance" and [YourClass class] if you want to lock "per class". (self) means that execution of the critical section needs to be synchronized for the current (particular) object.
weichsel
Ahhh, I get it! Thanks ever so much :-)
Michael Waterfall
+2  A: 

If you really do have something that you want to be processed one item at a time, my recommendation is to use NSOperations and an NSOperationQueue where you've set the maxConcurrentOperationCount to 1. If you make sure that the only way that this shared block of code is accessed is through operations in this queue, you'll do away with the need for expensive locks.

This may require a little reorganization of your application, but I've found that applying this within my own applications has led to better performance and cleaner code.

Brad Larson