Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >多线程(二):GCD

多线程(二):GCD

作者头像
Helloted
发布于 2022-06-07 05:27:53
发布于 2022-06-07 05:27:53
42900
代码可运行
举报
文章被收录于专栏:HellotedHelloted
运行总次数:0
代码可运行
1、添加任务到队列(同步、异步):
dispatch_sync:

同步添加,将指定的任务block同步追加到queue中,在追加的block结束之前,dispatch_sync会一直等待;

如果在主线程上执行同步任务(任务也在主线程执行),会造成死锁:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//会造成死锁
dispatch_sync(dispatch_get_main_queue(), ^{
	//
});

但是在异步任务里可以用来切换到主线程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_async(dispatch_get_global_queue(0,0), ^{
	//耗时操作;
	dispatch_sync(dispatch_get_main_queue(), ^{
		//回到主线程;
	});
});

可以用来阻塞线程:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_sync(dispatch_get_global_queue(0,0), ^{
  sleep(2);
  NSLog(@"2秒后执行,但是会阻塞线程");
});
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
   NSLog(@"2秒后执行,但是不阻塞线程");
});
dispatch_async:

异步添加,将指定的Block”非同步”地追加到指定的Queue中,该线程不做等待,继续往下执行;

2、队列

Dispatch Queue:执行处理任务的队列,通过dispatch_async等函数API,在Block语法中记述想要执行的处理任务并将其追加到Dispatch Queue中,Dispatch Queue按照追加的顺序(先进先出FIFO)执行处理。

Serial Dispatch Queue(串行队列):

等待现在执行中处理结束,一旦生成Serial Dispatch Queue并追加处理。系统对于一个Serial Dispatch Queue就只生成并使用一个线程,但是如果生成过多的线程,会导致消耗大量的内存,引起大量的上下文切换,大幅度降低系统的响应性能,因此只在为了避免多个线程更新相同的资源导致数据竞争时使用。

Concurrent Dispatch Queue(并行队列):

不等待现在执行中处理结束,可以并行执行多个处理,并行处理的处理数量取决于当前系统状态,生成所需的线程执行处理,当处理结束,应当执行的处理数减少时,XNU内核会结束不再需要的线程,因此当想并行执行不发生数据竞争等问题处理时使用并行队列,有效管理线程,不会出现太多线程。

系统默认有一个串行队列:主队列(main_queue)和并行队列:全局队列(global_queue),不需要自己手动释放,或者自己创建用户队列(需要手动释放)。

主队列(main):

dispatch_queue_t mainQ = dispatch_get_main_queue() 注意:不能sync向主队列提交任务,因为会造成死锁,只能async提交任务

全局队列(global_queue):并发队列

有执行优先级

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

DISPATCH_QUEUE_PRIORITY_HIGH:             //优先级最高,在default,和low之前执行
DISPATCH_QUEUE_PRIORITY_DEFAULT           //默认优先级,在low之前,在high之后
DISPATCH_QUEUE_PRIORITY_LOW               //在high和default后执行
DISPATCH_QUEUE_PRIORITY_BACKGROUND        //提交到这个队列的任务会在high优先级的任务和已经提交到background队列的执行完后执行。
获取队列:(create_queue):

如果是串行队列:dispatch_queue_create(“createName”, DISPATCH_QUEUE_SERIAL)

如果是并行队列:推荐使用dispatch_get_global_queue

如果需要用到barrier和group,才来dispatch_queue_create(“createName”,DISPATCH_QUEUE_CONCURRENT)

尽管是ARC,使用结束后也要dispatch_release释放

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_queue_t  concurrentQ = dispatch_queue_create("createName",DISPATCH_QUEUE_CONCURRENT)
dispatch_queue_t  serialQ = dispatch_queue_create("createName", DISPATCH_QUEUE_SERIAL)
改变队列优先级
dispatch_set_target_queue(restQueue, targetQueue);
暂停恢复队列
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_suspend(queue); //暂停队列queue
dispatch_resume(queue);  //恢复队列queue
3、延迟添加执行dispatch_after

并不是在多少秒后执行,而是在3秒后将任务添加到Dispatch Queue中

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3*NSEC_PER_SEC)),dispatch_get_main_queue(), ^{
	//秒
});

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,150ull *NSEC_PER_MSEC),dispatch_get_main_queue(), ^{
    //毫秒
});
4、dispatch_group与dispatch_barrier

dispatch_group应用于线程依赖:当添加到Queue中的所有任务都完成了,再来执行某个任务。

举例,异步下载两张图片,这在这两张图片下载完毕之后,将两张图片合成

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("com.gcd-group.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
    #异步下载第一张图片
 });
 
dispatch_group_async(group, queue, ^{
    #异步下载第二张图片
});
     
dispatch_group_notify(group, queue, ^{
    #两张图片下载完后进行合成
});

dispatch_barrier:barrier以为栅栏,阻碍。在串行队列中,无区别,但是在并行队列中,用这个函数添加的任务可以保证阻碍线程执行,即这个任务是串行执行的。可用于解决数据竞争问题。有个坑要注意,并行队列必必须是自己dispatch_queue_create创建的,不能用dispatch_get_global_queue

实现原理:queue中的其他block已经开始在各自分配的线程执行,当从queue检出一个barrier时,是等待其他的block都执行完毕再执行barrier,此时不会并发执行其他的block,直到该barrier执行完毕。 这相当于给当前已经运行的bock们加了一个group和notify,在notify里面执行了barrier,然后再执行barrier下面的block

举例。多个操作对数据库进行读写,读的操作可以异步进行,但是为了保证写的线程安全,则必须用dispatch_barrier

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_async(queue, ^{NSLog(@"read");});
dispatch_async(queue, ^{NSLog(@"read");});
dispatch_async(queue, ^{NSLog(@"read");});

#可以保证写的时候只有这一个操作
dispatch_barrier_sync(queue, ^{NSLog(@"writing");});

dispatch_async(queue, ^{NSLog(@"read");});
dispatch_async(queue, ^{NSLog(@"read");});
5、dispatch_semaphore

semaphore是信号的意思,dispatch_semaphore有三个函数,分别是dispatch_semaphore_create,dispatch_semaphore_signal,dispatch_semaphore_wait

dispatch_semaphore信号量控制

6、dispatch_apply

重复执行某段代码

在某些场景下使用dispatch_apply会对性能有很大的提升,比如你的代码需要以每个像素为基准来处理计算image图片。同时dispatch apply能够避免一些线程爆炸的情况发生

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//危险,可能导致线程爆炸以及死锁
for (int i = 0; i < 999; i++){
   dispatch_async(q, ^{...});
}
dispatch_barrier_sync(q, ^{});
// 较优选择, GCD 会管理并发
dispatch_apply(999, q, ^(size_t i){...});
7、dispatch_block_cancel

iOS8之后,提交到gcd队列中的dispatch block也可取消了,只需要简单的调用dispatch_block_cancel传入想要取消的block即可:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block1 = dispatch_block_create(0, ^{
    NSLog(@"block1 begin");
    [NSThread sleepForTimeInterval:1];
    NSLog(@"block1 done");
});
dispatch_block_t block2 = dispatch_block_create(0, ^{
    NSLog(@"block2 ");
});
dispatch_async(queue, block1);
dispatch_async(queue, block2);
dispatch_block_cancel(block2);
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
iOS - 多线程(三):GCD
GCD 中的任务有两种封装:dispatch_block_t 和 dispatch_function_t。
师大小海腾
2020/04/16
2.6K0
iOS - 多线程(三):GCD
推荐:多线程的实现方式及经典示例
iOS中实现多线程的技术方案 pthread 实现多线程操作 代码实现: void * run(void *param) { for (NSInteger i = 0; i < 1000; i
春哥大魔王
2018/04/16
1.2K0
推荐:多线程的实现方式及经典示例
iOS多线程——你要知道的GCD都在这里你要知道的iOS多线程NSThread、GCD、NSOperation、RunLoop都在这里
你要知道的iOS多线程NSThread、GCD、NSOperation、RunLoop都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本系列文章主要讲解iOS中多线程的使用,包括:NSThread、GCD、NSOperation以及RunLoop的使用方法详解,本系列文章不涉及基础的线程/进程、同步/异步、阻塞/非阻塞、串行/并行,这些基础概念,有不明白的读者还请自行查阅。本系列文章将分以下几篇文章进行讲解,读者可按需查阅。 iOS
WWWWDotPNG
2018/04/10
2K0
iOS 多线程:『GCD』详尽总结(二)
同步执行 + 主队列在不同线程中调用结果也是不一样,在主线程中调用会出现死锁,而在其他线程中则不会。
iOSSir
2023/03/19
6871
iOS 多线程:『GCD』详尽总结(二)
GCD概念和基本使用GCD概念和基本使用
总体来说涉及到串行队列的嵌套就容易出现死锁,使用时一定要注意;串行队列里添加同步任务队列必定会出现死锁;
用户8893176
2021/08/09
1.1K0
GCD概念和基本使用GCD概念和基本使用
《Objective-C-高级编程》干货三部曲(三):GCD篇
我们知道在iOS开发中,一共有四种多线程技术:pthread,NSThread,GCD,NSOperation:
用户1740424
2018/07/23
9640
《Objective-C-高级编程》干货三部曲(三):GCD篇
细说 GCD(Grand Central Dispatch)如何用
文中较详细介绍GCD队列,各种GCD使用方法,实例如何使用Dispatch Source监听系统底层对象,分析不同锁的性能对比,实例GCD死锁情况。文中的Demo在这里 https://github.com/ming1016/GCDDemo 对着文章试着来调demo体会更深哦,细细嚼消化好:)
用户7451029
2020/06/16
2.2K0
iOS_多线程一:GCD+混搭测试
Grand Central Dispatch 简称(GCD)是苹果公司开发的技术。以优化应用程序支持多核心处理器和其他的对称多处理系统的系统。
mikimo
2022/07/20
4690
iOS多线程:『GCD』详尽总结
本文首发于我的个人博客:『不羁阁』 文章链接:传送门 本文更新时间:2018-02-24 10:07:40 感谢大家对这篇文章的喜欢和支持。为了不辜负大家的喜欢,也为了更好的让大家了解 iOS 多线程,以及 GCD 的相关知识,我对这篇文章进行了重新梳理,在原有文章的基础上修改了原文存在的问题,并增加了更多关于 GCD 相关知识和使用方法,希望大家能够喜欢这篇新文章。 本文用来介绍 iOS 多线程中 GCD 的相关知识以及使用方法。这大概是史上最详细、清晰的关于 GCD 的详细讲解+总结的文
程序员充电站
2018/05/31
1K0
iOS 多线程总结
●进程是指在系统中正在运行的一个应用程序,就是一段程序的执行过程,我们可以理解为手机上的一个app。 ●每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内,拥有独立运行所需的全部资源。
赵哥窟
2019/09/27
7660
GCD API记录(二)
这是关于GCD的第二篇文章,GCD的API有100多个,通过快捷键Option + 单击,可以在Reference中的Grand Central Dispatch (GCD) Reference中看到。除了上篇文章介绍的几个外,其他用到的API就在这篇文章里记录。
Haley_Wong
2018/08/22
2.2K0
GCD API记录(二)
iOS--多线程之GCD
GCD 一、简单介绍 1.什么是GCD? 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 2.GCD的优势 GCD是苹果公司为多核的并行运算提出的解决方案 GCD会自动利用更多的CPU内核(比如双核、四核) GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程) 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码 3.提示 (1)GCD存在于libdispatch.dylib这个库中,这个调度库包含了GCD的所有的东西
用户1941540
2018/05/11
7100
iOS多线程之三:GCD的使用
一、什么是GCD GCD是Grand Central Dispatch的简称,它是基于C语言的。如果使用GCD,完全由系统管理线程,不需要编写线程代码。只需定义想要执行的任务,然后添加到适当的调度队列(dispatch queue)。GCD会负责创建线程和调度你的任务,系统直接提供线程管理。 二、GCD的使用 首先看下这段代码:
s_在路上
2018/09/11
3.1K0
iOS多线程之三:GCD的使用
iOS多线程编程
废话不多说,直接上干货。先熟悉一下基本知识,然后讲一下常用的两种,NSOperation和GCD。 一、基础概念 进程: 狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。 进程的概念主要有两点:第一,进程是一个实体。每一个进程都有
王大锤
2018/05/17
8890
iOS 多线程:『GCD』详尽总结(一)
任务:就是执行操作的意思,换句话说就是你在线程中执行的那段代码。在 GCD 中是放在 block 中的。执行任务有两种方式:同步执行(sync)和异步执行(async)。两者的主要区别是:是否等待队列的任务执行结束,以及是否具备开启新线程的能力。
iOSSir
2023/03/19
1.1K0
iOS 多线程:『GCD』详尽总结(一)
多线程-GCD
GCD是苹果为多核的并行运算提出的解决方案,所以会自动合理地利用更多的CPU内核(比如双核、四核),最重要的是它会自动管理线程的生命周期(创建线程、调度任务、销毁线程),完全不需要我们管理,我们只需要告诉干什么就行。同时GCD抽象层次最高,当然是用起来也最简单,只是它基于C语言开发,并不像NSOperation是面向对象的开发,而是完全面向过程的。
進无尽
2018/09/12
1.2K0
阿里、字节:一套高效的iOS面试题( 多线程 GCD底层原理篇)
dispatch_group_create() + dispatch_group_wait()
会写bug的程序员
2020/06/18
4.8K0
阿里、字节:一套高效的iOS面试题( 多线程 GCD底层原理篇)
GCD 概念解释方法:
概念解释 1. 执行任务的函数:在GCD中,任务是通过 block来封装的,并且任务的block没有参数也没有返回值。 同步:你必须把我的代码执行完你再走,一定要执行完同步里的代码再执行下面的代码 void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); 异步:你先走执行我下面的代码,我找人、找线程去执行我里面的代码 void dispatch_async(dispatch_queue_t queue, dispatch_bloc
用户2141756
2018/05/18
9090
GCD梳理与总结-常用API操练
定时器 GCD的定时器比NSTimer有更高的进度,而且避免了NSTimer的三大缺陷(RunLoop,不能跨越线程操作,内存泄漏风险)
ios-lan
2020/10/26
3600
GCD梳理与总结-常用API操练
iOS多线程 - GCD
GCD 全称 Grand Central Dispatch,可翻译为『牛逼的中枢调度器』。GCD 是纯 C 语言,提供了非常强大的函数。
hrscy
2018/08/30
7240
iOS多线程 - GCD
相关推荐
iOS - 多线程(三):GCD
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验