为什么我们在@synchronized块中传递self?

时间:2012-07-26 09:12:14

标签: objective-c ios macos synchronization block

我认为@synchronized块不依赖于对象但依赖于线程......对吗?在那种情况下,我们为什么要通过自我?

3 个答案:

答案 0 :(得分:20)

@synchronized是由语言提供的用于创建同步范围的构造。由于使用简单的全局共享互斥锁并因此序列化应用程序中的每个@synchronized范围非常低效,因此该语言允许我们指定同步点。

然后由开发人员决定哪个同步点适合该任务。

在实例方法中,使用self很常见:实例是同步点。 @synchronized(self)范围可以在任意数量的实例上调用,但对于给定的实例只能调用一次。每个@synchronized(self)范围都将针对给定实例进行序列化。

当然,如果您愿意,可以自由使用其他同步点。您可以使用课程(@synchronized(self.class))或其他任何符合您需求的内容。

答案 1 :(得分:4)

传入的对象用于区分哪些@synchronized块对应于相互锁定。使用self通常很方便,但如果您只想同步更小,更具体的代码部分(例如,同步对特定NSMutableDictionary的所有访问),则有时使用其他对象是个好主意。而不是同步整个实例中的所有内容)

我不确定“线程依赖”是什么意思。 @synchronized的目的是用于可能在不同线程上运行的代码块,并且您需要确保在任何时间只运行1次而不重叠。对于执行非线程安全的操作很重要(例如,变异集合)。

答案 2 :(得分:4)

我质疑这种做法,因为它是known anti-pattern in other languages。问题的关键在于,其他人也可以在您的对象上synchronize,可能导致死锁以及在您使用私有NSObject进行锁定时本不存在的其他问题。例如:

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