Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does @synchronized lock/unlock in Objective-C?

Does @synchronized not use "lock" and "unlock" to achieve mutual exclusion? How does it do lock/unlock then?

The output of the following program is only "Hello World".

@interface MyLock: NSLock<NSLocking> @end  @implementation MyLock  - (id)init {     return [super init]; }  - (void)lock {     NSLog(@"before lock");     [super lock];     NSLog(@"after lock"); }  - (void)unlock {     NSLog(@"before unlock");     [super unlock];     NSLog(@"after unlock"); }  @end   int main (int argc, const char * argv[]) {     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];      MyLock *lock = [[MyLock new] autorelease];     @synchronized(lock) {         NSLog(@"Hello World");     }      [pool drain]; } 
like image 260
David Lin Avatar asked Jul 31 '09 23:07

David Lin


People also ask

What is @synchronized self?

@synchronized(self) is used to get rid of the self. prefix.

What is lock in synchronized?

When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.

What is Objc_sync_enter?

objc_sync_enter is an extremely low-level primitive, and isn't intended to be used directly. It's an implementation detail of the old @synchronized system in ObjC. Even that is extremely out-dated and should generally be avoided. Synchronized access in Cocoa is best achieved with GCD queues.

What does synchronized mean java?

Synchronization in java is the capability to control the access of multiple threads to any shared resource. In the Multithreading concept, multiple threads try to access the shared resources at a time to produce inconsistent results. The synchronization is necessary for reliable communication between threads.


2 Answers

The Objective-C language level synchronization uses the mutex, just like NSLock does. Semantically there are some small technical differences, but it is basically correct to think of them as two separate interfaces implemented on top of a common (more primitive) entity.

In particular with a NSLock you have an explicit lock whereas with @synchronized you have an implicit lock associated with the object you are using to synchronize. The benefit of the language level locking is the compiler understands it so it can deal with scoping issues, but mechanically they behave basically the same.

You can think of @synchronized as a compiler rewrite:

- (NSString *)myString {   @synchronized(self) {     return [[myString retain] autorelease];   } } 

is transformed into:

- (NSString *)myString {   NSString *retval = nil;   pthread_mutex_t *self_mutex = LOOK_UP_MUTEX(self);   pthread_mutex_lock(self_mutex);   retval = [[myString retain] autorelease];   pthread_mutex_unlock(self_mutex);   return retval; } 

That is not exactly correct because the actual transform is more complex and uses recursive locks, but it should get the point across.

like image 178
Louis Gerbarg Avatar answered Dec 09 '22 23:12

Louis Gerbarg


In Objective-C, a @synchronized block handles locking and unlocking (as well as possible exceptions) automatically for you. The runtime dynamically essentially generates an NSRecursiveLock that is associated with the object you're synchronizing on. This Apple documentation explains it in more detail. This is why you're not seeing the log messages from your NSLock subclass — the object you synchronize on can be anything, not just an NSLock.

Basically, @synchronized (...) is a convenience construct that streamlines your code. Like most simplifying abstractions, it has associated overhead (think of it as a hidden cost), and it's good to be aware of that, but raw performance is probably not the supreme goal when using such constructs anyway.

like image 30
Quinn Taylor Avatar answered Dec 09 '22 22:12

Quinn Taylor