synchronized块和dispatch_async

Ali*_*aba 11 objective-c grand-central-dispatch ios dispatch-async ios6

当我们在块中调用dispatch_async()时,使用@synchronized()在IOS中锁定会发生什么.

例如:

    id myID
-(void) foobar
{
    @synchronized(myID){
        dispatch_async(){ //do stuff with myID};
    }
}
Run Code Online (Sandbox Code Playgroud)

锁定在dispatch_async调用中是否仍然有效?或者更重要的是在dispatch_async()中使用另一个@synchronized()调用有什么缺点吗?

Rob*_*Rob 10

假设您正在尝试myID在后台队列中同步与此对象的交互,那么您需要反过来,即调度块内的锁定.现在你有:

@synchronized(myID) {
    dispatch_async(queue, ^{
         // do stuff with myID
    });
}
Run Code Online (Sandbox Code Playgroud)

这是同步增加的派出块到队列的过程,但并没有同步你在后台做什么.我怀疑那不是你的意思.

你可能打算:

dispatch_async(queue, ^{
    @synchronized(myID) {
         // do stuff with myID
    }
});
Run Code Online (Sandbox Code Playgroud)

它看起来非常相似,但会导致完全不同的行为.现在,正在同步调度到后台队列的工作.

作为进一步的改进,如果这个调度块可能很慢(我认为它可能是),那么你可能想要尽可能地约束@synchronized块:

dispatch_async(queue, ^{

    // do slow stuff in preparation for interacting with `myID`

    @synchronized(myID) {
         // quickly do stuff with myID
    }

    // do anything else here
});
Run Code Online (Sandbox Code Playgroud)

如果您在块中执行所有后台块@synchronized,则可能无法将其分配到后台,即最小化对主队列的影响.最后的再现可以缓解这个问题.

作为最后的观察,如果你有一个串行队列(或者你用屏障进行更新的非全局并发队列),那么这通常被用作一种技术,只要所有的更新和查询都可以完全消除锁的需要for myID被分派到该队列.请参阅" 并发编程指南"中的"消除基于锁的代码".


Tom*_*mmy 4

那里的锁只会阻止同时调度两个不同的块。然而,它们是异步分派的,因此它们可能会在当时执行,也可能在将来任意遥远的时间执行。调度调用也不会等待他们完成。

所以块内的东西不同步。以最少的更改实现这一目标的选项是同步调度或仅在块内@synchronizing。

根据您正在做的事情,最好的想法可能是建立一个串行调度队列并将您的块调度到该队列上。