Why do we pass self in @synchronized block?
Asked Answered
B

3

13

I guess @synchronized blocks are not object dependent but thread dependent...right? In that case why do we pass self?

Burdick answered 26/7, 2012 at 9:12 Comment(0)
C
21

@synchronized is a construct provided by the language to create synchronized scopes. As it would be highly inefficient to use a simple global shared mutex, and thus serializing every single @synchronized scope in the application, the language allows us to specify a synchronization point.

Then it's up to the developer(s) to decide which synchronization points are appropriate for the task.

On an instance method, using self is common: the instance is the synchronization point. The @synchronized(self) scope can be called on any number of instances, but only once for a given instance. Every @synchronized(self) scope will be serialized for a given instance.

Of course, you are free to use another synchronization point if you want to do so. You can use the class (@synchronized(self.class)) or anything else that suits your needs.

Canorous answered 26/7, 2012 at 9:33 Comment(1)
Thanks! What I need to know exactly is how does the @synchronized(self) differ from @synchronized(self.class)? What I understood from your statement is, when we lock a block with @synchronized(self) it ensures that no two threads will run that block against an object. And when we use @synchronized(self.class), it will ensure that no two threads will run that block against any objects of that class. Am I correct?Burdick
S
5

I question this practice, as it is a known anti-pattern in other languages. The crux of the issue is that someone else could also synchronize on your object, possibly causing deadlocks and other issues that would not have been present had you been using a private NSObject for the lock. For example:

@implementation foo
-(void) bar
{
    @synchronized(self) {
        @synchronized(sharedLock) {
            //do something
        }
    }
}

Foo* foo = [[Foo alloc] init];
@synchronized(sharedLock) {
    @synchronized(foo) {
         //do something
    }
}

//in another thread
[foo bar];
Shepley answered 23/3, 2015 at 18:54 Comment(0)
H
4

The object passed in is used to differentiate which @synchronized blocks correspond to locking each other. Using self is often convenient, but sometimes it’s a good idea to use some other object if you want to only synchronise smaller, more specific sections of code (eg. synchronise all access to a specific NSMutableDictionary, rather than synchronising everything in the whole instance)

I’m not sure what you mean by “thread dependent”. The purpose of @synchronized is for blocks of code that may be running on different threads, and you need to ensure only 1 runs at any time, without overlapping. Important for performing actions that aren’t thread-safe (like mutating collections, for example).

Hithermost answered 26/7, 2012 at 9:27 Comment(1)
Oops – yes, it’s a typo. I must have missed that when I fixed all the other ones too :)Hithermost

© 2022 - 2024 — McMap. All rights reserved.