Why do we pass self in @synchronized block?

2020-06-03 02:32发布

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

3条回答
叛逆
2楼-- · 2020-06-03 02:36

@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.

查看更多
闹够了就滚
3楼-- · 2020-06-03 02:48

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];
查看更多
看我几分像从前
4楼-- · 2020-06-03 02:48

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).

查看更多
登录 后发表回答