2.GCD多线程整理

本文深入探讨了GCD(Grand Central Dispatch)的核心概念和技术细节,包括任务队列的创建、使用及管理,不同类型的队列及其适用场景,以及如何利用GCD实现线程间的同步与异步通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:该文整理自《Object-C高级编程》

1.任务队列

Dispatch Queue:FIFO结构的任务队列,等待线程处理,分成串行和并行两种模式。串行为单线程(同时被处理的任务只能有一个),并行为多线程,可以有多个任务被同时处理。

用户职能操作队列,而不能操作线程。

貌似并没有提供限制最大线程数量接口API。

serial dispatch queue:用在多个线程想更新相同的数据资源,这种方式能确保数据的安全

concurrent dispatch queue:不发生数据竞争的时,可以使用并行的队列 

 

2.API列表

//默认为串行队列

1.创建队列

dispatch_queue_t queid = dispatch_queue_create(“cc.app”, NULL);

DISPATCH_QUEUE_CONCURRENT 并行


2.释放队列(需手动释放,ARC并不负责队列释放)

dispatch_release(quid);

3.持有队列

dispatch_retain(queid); 

4.异步提交任务

dispatch_async(queid,^{…});

特别说明:异步提交的时候会隐式的调用dispatch_retain,确保队列可靠,被其它对象给释放

流程:

dispatch_create();

dispatch_async();

dispatch_release(); //提交后立即释放,也能确保任务能够被处理


进程的主线程队列和系统全局队列

5.获取主线程队列

dispatch_get_main_queue

6.获取全局队列

全局队列为并行队列有四种优先级:

DISPATCH_QUEUE_PRIORITY_LOW

DISPATCH_QUEUE_PRIORITY_DEFAULT

DISPATCH_QUEUE_PRIORITY_HIGH

DISPATCH_QUEUE_PRIORITY_BACKGROUND 

dispatch_get_global_queue

7.修改队列优先级

dispatch_set_target_queue

默认优先级为DISPATCH_QUEUE_PRIORITY_DEFAULT

可以修改queue的执行阶层

如果在多个serial queue中调用dispatch_set_target_queue,并且目标queue相同,那么这个时候原本本应并行执行的多个queue在目标中职能一次执行一个 ,由并行转串行,有没有先后顺序呢?


优先级设置方式ex:

dispatch_queue_t queid;

dispatch_queue_t global_que = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, NULL);

dispatch_set_target_queue(queid, global_que);

8.在指定多少时间后添加任务

dispatch_after

ex:3秒后追加到任务队列中

dispatch_time_t ntime = dispatch_time(DISPATCH_TIME_NOW, 3ull*NSEC_PER_SEC);

dispatch_after(time, dispatch_get_main_queue, ^{});

NSEC_PER_SEC 单位为秒

NSEC_PER_MSEC 单位为毫秒

 

dispatch_walltime 计算绝对时间,添加到指定队列


9.Dispatch group

等待一组任务完成后,通知,然后继续执行

dispatch_group_create 创建一个任务组

dispatch_group_async 向这个组提交任务

dispatch_group_notify 任务做完后通知

dispatch_group_wait 阻塞当前线程,进行阻塞

dispatch_release 释放

ex:

dispatch_queue_t queid = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, quid, ^{});

dispatch_group_async(group, quid, ^{});

dispatch_group_async(group, quid, ^{});

//任务做完后进行通知

dispatch_group_notify(group, dispatch_get_main_queue(), ^{});

dispatch_release(group);

//等待用法,返回为0表示任务都结束,否则未结束

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);


10.Dispatch Barrier

很强大的功能,有点类似读写锁,但由于读写锁(不会有饿死现象)

ex:

dispatch_async(queue, block0);

dispatch_async(queue, block1);

dispatch_async(queue, block2);

dispatch_async(queue, block3);

dispatch_barrier_async(queue, block_block);

dispatch_async(queue, block4);

dispatch_async(queue, block5);

dispatch_async(queue, block6);

状态分析:block0, block1, block2结束后,运行block_block

  然后并行运行block4, block5, block6

 

11.同步提交

dispatch_sync:同步提交任务,注意死锁

ex:如果以下代码在主线中运行则会死锁

dispatch_queue_t queid = dispatch_get_main_queue();

dispatch_sync(queid, ^{}); 

即:程在执行的时候会锁定自己的任务队列,当它自己向自己提交任务时,会进行再次加锁,这个时候就会造成死锁。

所以线程千万不要自己向自己提交任务,或者直接用异步方式也挺好


12.dispatch_apply按照指定的次数提交到任务队列,会等待任务结束


13.dispatch_suspend/dispatch_resume挂起或者唤醒队列,已经执行的任务不会停止


14.GCD方式的信号量

dispatch_semaphore_t semt = dispatch_semaphore_create(1);

dispatch_semaphore_wait(semt, DISPATCH_TIME_FORVER);  //返回值为0,获取了资源,否则超时

dispatch_semaphore_signal(semt);

dispatch_release(setmt);

15.dispatch_once 只执行一次初始化

static dispatch_once_t pred;

dispatch_once(&pred, ^{});

通过数据类型dispatch_once_t来进行保证

16.Dispatch IO

Page167,Page172,通过IO事件来进行驱动 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值