@synchronized()所接受的参数是什么?

9
我知道 @synchronized() 的作用,但是有时候我们会遇到以下情况:
1- @synchronized(self) 2- @synchronized([MyClass class]) 3- @synchrinized(myObj) 这三种情况有什么区别?我应该向这个块传递什么参数?

你应该传递 @synchronized(self)。 - Natarajan
1
@Natarajan,为什么?总是这样? - Basheer_CAD
@synchronize() 应该和 NSLock 差不多,用于使代码线程安全。 - Anil Varghese
你应该确定需要传递哪个参数 @Anil。 - Basheer_CAD
2个回答

14

根据文档

传递给@synchronized指令的对象是一个唯一的标识符,用于区分受保护的块。如果您在两个不同的线程中执行前面的方法,并在每个线程上传递一个不同的anObj参数,则每个线程都会获取其锁并继续处理而不被其他线程阻塞。但是,如果在两种情况下都传递相同的对象,则其中一个线程将首先获取锁,而另一个线程将被阻塞,直到第一个线程完成关键部分。

所以这取决于您想要保护哪些同时执行的内容,并且三种情况都有其应用。

例如,在

-(void)addToMyArray1:(id)obj
{
    @synchronized(self) {
        [self.myArray1 addObject:obj];
    }
}

-(void)addToMyArray2:(id)obj
{
    @synchronized(self) {
        [self.myArray2 addObject:obj];
    }
}

两个使用 @synchronized 块的线程不能同时执行,因为它们在同一个实例(self)上调用该方法,从而保护了不同线程对数组的同时访问。

但是,它还阻止第一个方法的块与第二个方法的块同时执行,因为它们使用同一个锁self。因此,为了更细粒度的锁定,您可以使用不同的锁:

-(void)addToMyArray1:(id)obj
{
    @synchronized(self.myArray1) {
        [self.myArray1 addObject:obj];
    }
}

-(void)addToMyArray2:(id)obj
{
    @synchronized(self.myArray2) {
        [self.myArray2 addObject:obj];
    }
}
现在从不同线程同时访问self.myArray1self.myArray2仍然受到保护,但互相独立。
可以使用对的锁来保护对全局变量的访问。这只是一个演示目的的简单例子。
static int numberOfInstances = 0;

-(id)init
{
    self = [super init];
    if (self) {
        @synchronized([self class]) {
            numberOfInstances++;
        }
    }
}

每次都传递self,比传递临界区更好,对吧?在这种情况下,_obj。 - Basheer_CAD
@Basheer_CAD:我不明白你的问题。_obj 是什么? - Martin R
我正在使用一种方法来更改_obj(由多个线程编写),最好使用@synchronized(_obj),然后在{...}内部更改此对象。以防万一,self被用作其他@synchr块中的令牌,来自另一个线程? - Basheer_CAD
@Basheer_CAD:是的,如果您要保护单个对象(如我答案中的阵列),那么您只需锁定此对象(实际上这更简单,我已相应更新了答案)。-但可能存在更复杂的情况(例如需要保护的语句序列)需要专用锁。 - Martin R
如果我理解正确,第一个示例是同时保护array1和array2吗? - Zigii Wong

-2

@synchronized 应该每次传递相同的对象。所以 @synchronized(self) 是最好的选择。


1
这取决于你想要保护什么。@synchronized([MyClass class])或者@ synchronized(someObj)也有它们的使用场景。 - Martin R
@MartinR,是的,当你有一个单例时可能会这样。 - Basheer_CAD
如果您有一个单例,那么没有区别,因为只有一个实例。不,这取决于情况。如果对于同一类的任何其他对象执行相同的代码会成为问题,则在类上进行同步。还要记住:应该尽可能短地使用“@synchronized”(因此在“@synchronized”之外进行所有计算),并尝试避免在不同对象上嵌套“@synchronized”语句以避免死锁。 - gnasher729

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