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

13

我猜@synchronized块不是基于对象而是基于线程的...对吗?如果是这样,为什么要传递self?

3个回答

21

@synchronized 是一种语言提供的构造,用于创建同步作用域。由于使用简单的全局共享互斥锁会非常低效,从而使应用程序中的每个@synchronized作用域都被序列化,因此语言允许我们指定同步点。

然后开发人员可以决定哪些同步点适合完成任务。

在实例方法中,使用self是常见的:实例是同步点。 @synchronized(self) 作用域可以在任意数量的实例上调用,但对于给定的实例只能调用一次。对于给定实例,每个@synchronized(self)作用域将被串行化。

当然,如果需要,可以自由选择其他同步点。您可以使用类(@synchronized(self.class))或任何其他适合您需求的东西。


5
谢谢!我需要确切了解@synchronized(self)和@synchronized(self.class)之间的区别。从您的陈述中,我理解到当我们使用@synchronized(self)锁定一个块时,它会确保没有两个线程会针对一个对象运行该块。而当我们使用@synchronized(self.class)时,它将确保没有两个线程会针对该类的任何对象运行该块。我的理解正确吗? - Advaith

5

我对这种做法持怀疑态度,因为它在其他语言中是已知的反模式。问题的关键在于,其他人也可能在你的对象上进行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];

4
传递进来的对象用于区分哪些@synchronized块相互对应以进行锁定。使用self通常很方便,但有时如果您希望仅同步更小、更具体的代码部分(例如同步对特定的NSMutableDictionary的所有访问,而不是同步整个实例中的所有内容),则使用其他对象可能是一个好主意。
我不确定您所说的“线程相关”是什么意思。 @synchronized的目的是用于在可能运行在不同线程上的代码块,需要确保每次仅运行1个且不重叠。这对于执行不支持线程安全的操作(例如改变集合等)非常重要。

哎呀,是的,这是个打字错误。我修复其他所有错误时可能错过了它 :) - DouglasHeriot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接