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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了{objccn.io}学习笔记-并发编程-底层并发API相关的知识,希望对你有一定的参考价值。

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的主要内容,如果未能解决你的问题,请参考以下文章

太硬核了!GitHub上堪称完美的神仙并发编程笔记,请收下我的下巴

《Java并发编程的艺术》读后笔记-part2

java并发编程艺术学习第二章 java并发机制的底层实现原理 学习记录 volatile

《Java虚拟机并发编程》学习笔记

Java并发编程学习笔记

多线程编程学习笔记——使用并发集合