@synchronized(self) - 最好的方法

时间:2016-03-18 15:28:54

标签: ios synchronization synchronized

我目前开始研究@synchronized如何工作,以及它如何锁定对象。

@synchronized(self) {
    [self getDataWithCompletionBlock:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [refreshControl endRefreshing];
            [self.collectionView reloadData];
            loadingView.hidden = YES;
            self.oneTimeCallReach = NO;
        });
    }];
}

这完全错了吗?

1 个答案:

答案 0 :(得分:1)

I assume you are updating some model objects asynchronously inside getDataWithCompletionBlock. Unfortunately, the code you posted will not synchronize asynchronous updates. Neither those updates, nor your completion block, itself, will be synchronized with that code.

Assuming you want to synchronize data that is asynchronously retrieved, you should:

  • remove the synchronized directive wrapping your method call;

  • don't update model objects inside the method;

  • instead, just retrieve it to a local variable which you then pass back in an additional parameter to the completion block;

  • then, in your completion block, perform the model update using the parameter passed to the block, synchronizing it as needed.

By the way, if you dispatch the updating of the model to the main queue, you may be able to retire synchronized directive entirely and instead use the main thread to synchronize all updates. (Dispatching updates and access to a serial queue is perfectly acceptable way to synchronize access from multiple threads, and main queue is, itself, a serial queue.) If all read and writes to the model take place on the main thread, that achieves the necessary synchronization. Obviously, though, if you're accessing the model from other threads, then you will need to synchronize it. But often restricting access to the model to the main thread is a nice, simple synchronization mechanism. As Apple says in their Concurrency Programming Guide

  

完全避免同步

     

对于您正在处理的任何新项目,甚至是现有项目,设计代码和数据结构以避免同步是最佳解决方案。虽然锁和其他同步工具很有用,但它们确实会影响任何应用程序的性能。如果整体设计导致特定资源之间存在高争用,那么您的线程可能会等待更长时间。

     

实现并发的最佳方法是减少并发任务之间的交互和相互依赖关系。如果每个任务都在自己的私有数据集上运行,则不需要使用锁保护该数据。即使在两个任务共享公共数据集的情况下,您也可以查看设置分区的方法或为每个任务提供自己的副本。当然,复制数据集也有其成本,因此在做出决定之前,您必须权衡这些成本与同步成本。

无论如何,如果你想最小化他需要自己同步,它可能看起来像:

[self getDataWithCompletionBlock:^(NSArray *results){
    dispatch_async(dispatch_get_main_queue(), ^{
        self.objects = results;
        [refreshControl endRefreshing];
        [self.collectionView reloadData];
        loadingView.hidden = YES;
        self.oneTimeCallReach = NO;
    });
}];

现在,显然,我不知道你的模型是什么,所以我的NSArray例子可能不对,但希望这说明了这个想法。让完成处理程序处理同步更新(如果您没有任何其他线程直接访问模型,则使用主队列来同步访问)。

就个人而言,我可能还会包含一些错误参数,以便更新UI的块可以检测并处理可能发生的任何错误。