当我们在块中调用dispatch_async()时,使用@synchronized()在IOS中锁定会发生什么。
例如:
id myID
-(void) foobar
{
@synchronized(myID){
dispatch_async(){ //do stuff with myID};
}
}
在dispatch_async调用中锁是否仍然有效?或者更重要的是在dispatch_async()中使用另一个@synchronized()调用有什么缺点吗?
答案 0 :(得分:10)
假设您正在尝试与后台队列中的此myID
对象同步交互,那么您需要反过来,即调度块内的锁定。现在你有:
@synchronized(myID) {
dispatch_async(queue, ^{
// do stuff with myID
});
}
这是同步将调度块添加到队列的过程,但不同步你在后台执行的操作。我怀疑那不是你的意思。
您可能打算:
dispatch_async(queue, ^{
@synchronized(myID) {
// do stuff with myID
}
});
它看起来非常相似,但导致完全不同的行为。现在,调度到后台队列的工作正在同步。
作为进一步的改进,如果这个调度块可能很慢(我认为它可能是),那么你可能想要尽可能地约束@synchronized
块:
dispatch_async(queue, ^{
// do slow stuff in preparation for interacting with `myID`
@synchronized(myID) {
// quickly do stuff with myID
}
// do anything else here
});
如果您在@synchronized
块中执行了所有后台阻止,则可能无法将其分配到后台,即最小化对主队列的影响。最后一次演绎减轻了这个问题。
作为最后的观察,如果你有一个串行队列(或者你使用屏障进行更新的非全局并发队列),这通常被用作一种技术,可以完全消除对锁的需要,只要所有myID
的更新和查询将分派到该队列。请参阅并发编程指南中的Eliminating Lock-Based Code。
答案 1 :(得分:3)
那里的锁只会阻止一次调度两个不同的块。然而,它们是异步调度的,因此它们可以在当时执行,或者可以在将来任意执行。调度电话也不会等待他们完成。
因此块内的东西不同步。实现最小变化的选项是同步调度或仅在块内进行@synchronizing。
根据您正在做的事情,最好的想法可能是建立一个串行调度队列并将您的块分配给它。