如何等待@synchronized块内的完成处理程序?
问题描述:
我想在临界区内同步调用一个完成处理程序(使用@synchronized block)。我试图等待使用信号量的完成处理程序,但信号量信号永远不会被调用。如何等待@synchronized块内的完成处理程序?
下面是我在做什么:
NSNumber *lock = 0;
@synchronized(lock) {
// critical section code begins
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self someMethodWithCompletionHandler:^(BOOL result) {
// execute completion handler
dispatch_semaphore_signal(sema);
}];
// wait for completion block to finish
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// critical section code ends
}
我相信,由于@synchronized块完成处理程序被调用同一个线程,导致死锁的呼叫者。是对的吗?如果是的话,还能如何实现?
谢谢!
答
我会避免@synchronized
并使用串行调度队列来序列化关键部分中的工作。您仍然可以使用信号量来阻塞串行调度队列,直到异步操作完成。
串行调度队列保证一次只有一个代码块可以进入临界区,并且不存在阻塞主队列的风险。
你需要你的类初始化
@property (strong,nonatomic) dispatch_queue_t serialQueue;
- (id)init {
if (self = [super init]) {
self.serialQueue = dispatch_queue_create("com.example.CriticalTaskQueue", NULL);
}
return self;
}
- submitSomeCriticalWork() {
dispatch_async(self.serialQueue, ^{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self someMethodWithCompletionHandler:^(BOOL result) {
// execute completion handler
dispatch_semaphore_signal(sema);
}];
// wait for completion block to finish
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// critical section code ends
}];
}
它通常是一个坏主意,试图使异步事情同步过程中创建的串行队列。你需要确保'someMethodWithCompletionHandler'既能完成它的工作,又能将不同的队列上的完成处理程序分派给你用'等待'来阻塞的那个队列。如果你在主队列中等待,那很糟糕。添加一个同步块使其更加复杂,因为您现在有第二个潜在的等待和死锁触发器。 – Paulw11
与其使用@syncrhonized块,我会在专用串行调度队列上异步调度整个关键段,并在另一个实用程序队列或主队列上异步调度'someMethodWithCompletionHandler'。然后你的信号量可以安全地阻止你的私人队列。 – Paulw11
但我希望临界区代码是同步的。不要将整个临界区异步调度到另一个串行线程使其异步?在临界区完成后应执行的临界区之后,我有代码。 –