ios - @synchronized (self) - 最好的方法

标签 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;
        });
    }];
}

这是完全错误的吗?

最佳答案

我假设您正在 getDataWithCompletionBlock 中异步更新一些模型对象。不幸的是,您发布的代码不会同步异步更新。这些更新和您的完成 block 本身都不会与该代码同步。

假设您要同步异步检索的数据,您应该:

  • 删除包装方法调用的同步指令;

  • 不要在方法内更新模型对象;

  • 相反,只需将它检索到一个局部变量,然后将其作为一个附加参数传回完成 block ;

  • 然后,在您的完成 block 中,使用传递给该 block 的参数执行模型更新,并根据需要进行同步。

顺便说一下,如果您将模型的更新分派(dispatch)到主队列,您可以完全取消 synchronized 指令,而是使用主线程来同步所有更新。 (调度更新和访问串行队列是同步多个线程访问的完全可接受的方式,主队列本身就是一个串行队列。)如果对模型的所有读取和写入都发生在主线程上,则实现了必要的同步。但显然,如果您从其他线程访问模型,则需要同步它。但通常将对模型的访问限制在主线程是一种很好、简单的同步机制。正如 Apple 在他们的 Concurrency Programming Guide 中所说的那样:

Avoid Synchronization Altogether

For any new projects you work on, and even for existing projects, designing your code and data structures to avoid the need for synchronization is the best possible solution. Although locks and other synchronization tools are useful, they do impact the performance of any application. And if the overall design causes high contention among specific resources, your threads could be waiting even longer.

The best way to implement concurrency is to reduce the interactions and inter-dependencies between your concurrent tasks. If each task operates on its own private data set, it does not need to protect that data using locks. Even in situations where two tasks do share a common data set, you can look at ways of partitioning that set or providing each task with its own copy. Of course, copying data sets has its costs too, so you have to weigh those costs against the costs of synchronization before making your decision.

无论如何,如果你想尽量减少他同步自己的需要,它可能看起来像:

[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 的 block 可以检测和处理可能发生的任何错误。

关于ios - @synchronized (self) - 最好的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36088304/

相关文章:

objective-c - NSUserDefaultsDidChangeNotification : What's the name Of the Key, 已更改?

c++ - pthreads 中的条件变量和释放多个锁

android - Android 和 MongoDB 上的 SQLite 同步

iphone - 检查 NSURLRequest 目标是否为 "_blank"?

IOS Objective-c - 让联系人不起作用 - 没有请求提示 - 访问被拒绝

ios - SWIFT - UIDatePicker - 开始和结束日期选择,但无法弄清楚如何将这两个日期调用到两个不同的文本框中

c++ - 使 TBB 管道过滤器超时

Java:帮助设计解决由 SQLite 引起的死锁

java - 同步对象在 notifyAll() 之前未被线程锁定

java - Collection.synchronizedMap 与同步 HashMap 中的各个方法