码迷,mamicode.com
首页 > Windows程序 > 详细

{objccn.io}学习笔记-并发编程-底层并发API

时间:2016-06-07 20:41:56      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:

1.不要在GCD中干『持久』的事

GCD 通过创建所谓的线程池来大致匹配 CPU 内核数量。要记住,线程的创建并不是无代价的。每个线程都需要占用内存和内核资源。这里也有一个问题:如果你提交了一个 block 给 GCD,但是这段代码阻塞了这个线程,那么这个线程在这段时间内就不能用来完成其他工作——它被阻塞了。为了确保功能点在队列上一直是执行的,GCD 不得不创建一个新的线程,并把它添加到线程池。

如果你的代码阻塞了许多线程,这会带来很大的问题。首先,线程消耗资源,此外,创建线程会变得代价高昂。创建过程需要一些时间。并且在这段时间中,GCD 无法以全速来完成功能点。有不少能够导致线程阻塞的情况,但是最常见的情况与 I/O 有关,也就是从文件或者网络中读写数据。正是因为这些原因,你不应该在GCD队列中以阻塞的方式来做这些操作。看一下下面的输入输出段落去了解一些关于如何以 GCD 运行良好的方式来做 I/O 操作的信息。

2.单一资源的多读单写

我们能够改善上面的那个例子。GCD 有可以让多线程运行的并发队列。我们能够安全地使用多线程来从 NSMutableDictionary 中读取只要我们不同时修改它。当我们需要改变这个字典时,我们使用 barrier 来分发这个 block。这样的一个 block 的运行时机是,在它之前所有计划好的 block 完成之后,并且在所有它后面的 block 运行之前。

以如下方式创建队列:

self.isolationQueue = dispatch_queue_create([label UTF8String], DISPATCH_QUEUE_CONCURRENT);

并且用以下代码来改变setter函数:

- (void)setCount:(NSUInteger)count forKey:(NSString *)key
{
    key = [key copy];
    dispatch_barrier_async(self.isolationQueue, ^(){
        if (count == 0) {
            [self.counts removeObjectForKey:key];
        } else {
            self.counts[key] = @(count);
        }
    });
}

 当使用并发队列时,要确保所有的 barrier 调用都是 async 的。如果你使用 dispatch_barrier_sync ,那么你很可能会使你自己(更确切的说是,你的代码)产生死锁。写操作需要 barrier,并且可以是 async 的。

关于dispatch_barrier_async的更多解释,请看这篇我翻译过的GCD的介绍和使用:iOS学习篇之Grand Central Dispatch(GCD)

3.

异步调用不会产生死锁。因此值得我们在任何可能的时候都使用异步分发。我们使用一个异步调用结果 block 的函数,来代替编写一个返回值(必须要用同步)的方法或者函数。这种方式,我们会有更少发生死锁的可能性。

异步调用的副作用就是它们很难调试。 

 

{objccn.io}学习笔记-并发编程-底层并发API

标签:

原文地址:http://www.cnblogs.com/emmet7life/p/5567221.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!