了解 Swift 中的 DispatchQueue Barrier 如何使用及常用场景
内容提要
在iOS中,可以使用DispatchQueue Barrier对并发队列中的任务进行同步调度,将线程不安全的目标转换为线程安全的目标。Dispatch Barrier API可以保证提交的任务在指定队列中唯一执行。可以通过示例代码了解Barrier的使用场景和注意事项。另外,还介绍了多读单写的技术实现方式,包括使用DispatchQueue和pthread_rwlock_t。读写锁提供了一种处理共享资源并发访问的有效方法,提高了性能和减少了线程之间的竞争。
延伸解读
Barrier 的队列限制与常见误区
文章强调,Barrier 任务必须提交到自定义的并发队列才能生效。如果使用串行队列或全局并发队列,Barrier 的行为会退化为普通的 dispatch_async,失去同步点的作用。这一点容易被忽略,因为全局队列虽然也是并发的,但系统并不保证 Barrier 的独占性。因此,在实际编码中,若想利用 Barrier 实现多读单写,务必自行创建并发队列,并避免误用全局队列。
多读单写:Barrier 与读写锁的对比
文章给出了两种多读单写的实现:DispatchQueue Barrier 和 pthread_rwlock。Barrier 方案基于 GCD,代码更 Swift 化,读操作使用 sync,写操作使用 async(flags: .barrier),适合与现有 GCD 代码集成。pthread_rwlock 则更底层,需要手动初始化和销毁锁,但提供了明确的读锁和写锁语义。两者都能实现读并发、写独占,选择取决于项目对性能、可移植性和代码风格的偏好。
Barrier 执行顺序的实际观察
示例代码的日志显示,任务一和任务三的输出顺序是乱序的,证明它们并发执行;而任务二的输出严格升序,且全部在任务一之后、任务三之前完成。这验证了 Barrier 的同步点作用:Barrier 之前提交的任务必须全部完成,Barrier 任务才会执行,之后的任务则等待 Barrier 完成。注意,异步添加任务后立即返回,所以 add complete 的打印会先于任务执行,这属于正常现象。
Q&A
DispatchQueue Barrier 在 iOS 中的主要作用是什么?
DispatchQueue Barrier 用于同步调度并发队列中的任务,将线程不安全的目标转换为线程安全的目标。
如何使用 DispatchQueue Barrier 进行任务调度?
可以通过创建自定义的并发队列,并在该队列中使用 .barrier 标志提交任务来实现任务调度。
使用 DispatchQueue Barrier 时需要注意什么?
指定的队列必须是自定义创建的并发队列,不能是串行队列或全局并发队列。
什么是多读单写场景?
多读单写场景允许多个线程同时读取数据,但写操作和写操作同一时间只能执行一个。
如何实现多读单写的技术?
可以使用 DispatchQueue Barrier 或 pthread_rwlock_rdlock 和 pthread_rwlock_wrlock 来实现多读单写。
读写锁的功能是什么?
读写锁允许多个线程同时读取数据,但保证一次只有一个线程可以写入资源,从而提高性能并减少线程竞争。