0

There is one thing I am not sure about when it comes to locks. I've read http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW16 but one thing I am not sure about; does @synchronize (or just mutex in general) protect only a section of code (say inside a method) or lock the entire object as a whole?

For example, two threads working on these methods, which modify an array;

@synthesize m_myMutableArray;

-(void)threadA
{
    @synchronized(m_myMutableArray) {
         [m_myMutableArray removeAllObjects];
    }
}

-(void)threadB
{
    NSInteger asdf = 1;
    @synchronized(m_myMutableArray) {
         [m_myMutableArray addObject:asdf];

}

Does @synchronized not do anything because they are two separate blocks of code, or is it the same mutex being locked in both methods, meaning m_myMutableArray is threadsafe?

Thanks

KaiserJohaan
  • 9,028
  • 20
  • 112
  • 199
  • Related: [Are @synchronized blocks guaranteed to release their locks?](http://stackoverflow.com/q/7735799/557219) Kevin’s answer should answer your question as well: it is the same mutex so long as the object being pointed to by `m_myMutableArray` is the same. –  Nov 11 '11 at 08:37
  • possible duplicate of [How does @synchronized lock/unlock in Objective-C?](http://stackoverflow.com/questions/1215330/how-does-synchronized-lock-unlock-in-objective-c) –  Nov 11 '11 at 08:42
  • Do I also have to use the @synchronized directive every time I am about to access the m_myMutablearray? For example, if threadB did not use the synchronized directive, would it still block if threadA locked it before? – KaiserJohaan Nov 11 '11 at 08:44
  • Yes, you should use it whenever you access the array. No, if threadB didn’t use `@synchronized`, it wouldn’t block if threadA locked it before, which is problematic since `NSMutableArray` isn’t thread-safe. –  Nov 11 '11 at 08:47
  • That would mean quite alot of locks due to the array being used at several places. If threadA was the mainthread, could I simply use performSelectorOnMainThread whenever threadB needed to access it,and they would queue up in the same thread and be safe? – KaiserJohaan Nov 11 '11 at 08:56

1 Answers1

3

The "argument" to @synchronized is a so-called token or key so you can have different locked sections. They only block each other when they have the same token. The object themselves are not "locked".

So if you have two @synchronized(foo) and two @synchronized(bar), the foo sections block each other but will not block the bar sections.

If possible, you should avoid @synchronized as it's very slow, due to its dynamic nature.

DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • if threadA is the mainthread, could I use performSelectorOnMainThread for all interfering operations in threadB? – KaiserJohaan Nov 11 '11 at 09:19
  • You mean, to avoid locking altogether? Depending on what you want to do this is an option. But note that if you set *waitUntilDone:YES* then threadB will block until the main has finished its current run loop iteration and can then perform your selector. Most of the time is way slower than locking. – DarkDust Nov 11 '11 at 09:33
  • If I do not waitUntillDone (it is callbacks updating a UI elements like a ListView) is it a good solution? – KaiserJohaan Nov 11 '11 at 09:38
  • Yes, it's OK. I do this a lot as well. – DarkDust Nov 11 '11 at 09:51