熟悉多线程的朋友,应该都遇到过这样的应用场景:
多个线程去读写数据。那么试想一下如果一条线程正在读取数据的时候另外一条线程同时在写数据。这种场景是否会产生问题呢?
我们期望这样一个线程,可以被我们反复利用,那么这又是如何实现的呢?
接下来我们一一介绍
如何解决多个线程对同一块资源的读写问题呢?
试想一下,当一个线程在读取资源的时候,正好有另外一个线程修改了这个资源,或者多个线程同时修改资源,这两种情况都会导致数据错乱。所以为了避免这种问题的产生我们应该怎么处理呢?
我们在多线程读写的时候应该有以下原则:
- 读者、读者并发
- 读者、写者互斥
- 写者、写者互斥
满足以上原则,我们就可以很好的结局上述问题。满足以上原则的话,系统给我们提供了很好用的API
:dispatch_barrier_async
,它可以很好的将我们的读写操作分离,原则上我们允许多个读取线程同时读取数据,假如说有写线程的话,通过上述dispatch_barrier_async
就可以将它之前的读操作隔离开来,同样的如果它后面还有读取线程的话也必须等到,写数据线程执行完之后才会执行。
具体的用法呢,就是通过调用dispatch_barrier_async
将写任务提交到一个自定义的并发队列concurrent_queue
中,而读取操作呢用过调用dispatch_sync
将读取操作以同步的方式提交到自定义的并发队列concurrent_queue
中。
接下来我们看具体的实现:
我们声明一个类MultiReadSingle
Write
1 | // 接口部分 |
没错,就是这么简单,相信你看了我的介绍,对多读单写应该很清楚了。接下来我们来介绍上述第二个问题。
如何创建一个可以反复使用的线程呢?
反复使用的线程说白了就是我们通常所说的 常驻线程。那么改如何创建呢?需要满足一下三点:
- 为当前线程开启一个
RunLoop
- 向该RunLoop中添加一个
Port/Sources
等维持RunLoop
的事件循环 - 启动该
RunLoop
我们看代码实现:
1 | // 接口部分 |
到这里,我们上述的两个问题就介绍完了,欢迎勘误!