How does this recursive synchronized call not dead

2019-05-26 18:55发布

问题:

I have a set of methods that all synchronize to the class object (can't use self, because multiple instances of this object could be used in multiple threads). Some of those methods call other methods in the class that also synchronize on the class object. Somehow this works and does not cause the deadlock I would expect it to.

I would assume that testA would be blocked from running because testB already has a lock on the class object, but this apparently isn't the case.

Is it something special that @synchronized is doing or is this a feature of the underlying mutex locks?


Example code that works:

- (NSUInteger)testA
{
    @synchronized(self.class)
    {
        NSLog(@"Doing something in A");
    }
    return 1;
}

- (void)testB
{
    @synchronized(self.class)
    {
        NSLog(@"Doing something in B");
        NSLog(@"A returned: %i", [self testA]);
    }
}

When calling testB the output is:

Doing something in B
Doing something in A
A returned: 1

回答1:

Mauricio's comment is correct. From TOCPL:

The Objective-C synchronization feature supports recursive and reentrant code. A thread can use a single semaphore several times in a recursive manner; other threads are blocked from using it until the thread releases all the locks obtained with it; that is, every @synchronized() block is exited normally or through an exception.