Why do we pass self in @synchronized block?

为君一笑 提交于 2019-12-03 16:24:54

问题


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


回答1:


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




回答2:


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




回答3:


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];


来源:https://stackoverflow.com/questions/11666014/why-do-we-pass-self-in-synchronized-block

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!