iOS-底层原理26-GCD补充和锁

《iOS底层原理文章汇总》
上一篇文章《iOS-底层原理25-GCD(下)》介绍了GCD单例,栅栏函数,同步函数,信号量底层原理,本文接着介绍GCD调度组合dispatch_source以及锁

1.调度组:dispatch_group_enter和dispatch_group_leave要成对出现,如下载两张图片完成后更新UI,两个异步线程任务会进入同一个组,只有等两个线程任务都leave之后才会进行通知

image.png

image.png

若将通知移到前面dispatch_group_notify并不需要保证两个线程组任务都完成,只需保证enter和leave是成对出现的就OK,不管远近


image.png

若多写一个dispatch_group_enter,则会回不到dispatch_group_notify中
image.png

若多写一个dispatch_group_leave,则会崩溃,奔溃的位置dispatch_group_leave(group)会最后执行,因为里面的任务有延迟sleep(1)


image.png

也可以将dispatch_group_leave(group)写到touchBegan中,控制dispatch_group_notify,点击屏幕,触发dispatch_group_leave(self.group)通知dispatch_group_notify回到主线程更新UI
image.png

dispatch_group_async和(dispatch_group_enter,dispatch_group_leave)起到相同的效果,执行完后触发dispatch_group_notify
image.png

dispatch_group_enter,dispatch_group_leave,dispatch_group_notify,dispatch_group_async底层原理呢?dispatch_group_enter,dispatch_group_leave为什么等价于dispatch_group_async?dispatch_group_async里面是否包含dispatch_group_enter和dispatch_group_leave
image.png

2.dispatch_source:有很多种类型如DISPATCH_SOURCE_TYPE_DATA_ADD,DISPATCH_SOURCE_TYPE_DATA_REPLACE,DISPATCH_SOURCE_TYPE_TIMER等并不依赖与runloop,和下层内核workLoop进行交互,调用时DISPATCH_SOURCE_TYPE_TIMER会很准确

image.png

image.png

image.png

3.信号量

image.png

4.锁的性能

  • 1.在全局并发队列里面买票,若不能保证原子性同步状态,会发生票絮乱,加上同步锁后,保证数据的原子性


    image.png
  • 2.@synchronized(self)底层原理,先符号断点查看汇编信息发现有两个标记位一个是objc_sync_enter,一个是objc_sync_exit


    image.png

    image.png
  • 3.clang查看@synchronized(self)源码,objc_sync_enter(_sync_obj)和objc_sync_exit(_sync_obj)分别在哪个源码里面呢?继续看汇编发现源码在libobjc.A.dylib


    image.png

    image.png
  • 4.递归锁是一种带有递归性质的互斥锁,进入objc_sync_enter和objc_sync_exit源码分析


    image.png
  • I.obj为nil的情况,objc_sync_nil(),下符号断点objc_sync_nil,传入的obj为nil,则什么都没做


    image.png

    image.png

    image.png

    image.png

    image.png
  • II.objc_sync_enter中obj不为nil的情况SyncData* data = id2data(obj,ACQUIRE)进行data->mutex.lock(),在objc_sync_enter中obj不为nil的情况下进行data->mutex.tryUnlock()解锁,加锁与解锁成对存在


    image.png

    image.png
  • 递归互斥锁:recursive_mutex_t
  • 嵌套 - 可重入 - 递归
  • lockCount
    enter:lockCount++,通过lockCount判断任务代码块被锁了多少次,间接验证可嵌套(可重入),可重复被锁


    image.png
objc_sync_enter : lock
objc_sync_enter : unlock

static SyncData* id2data(id object, enum usage why)底层原理分析


image.png

objc_sync_enter和objc_sync_exit会分别调用SyncData* data = id2data(obj, ACQUIRE)和SyncData* data = id2data(obj, RELEASE)传入ACQUIRE、RELEASE对应lockCount++、lockCount--进行代码复用,代码进出都会调用


image.png

可以对代码块进行多线程重复锁,若要从内存中获取一把锁,应该设计成什么结构,方便于查找和断开,设计成哈希表的拉链形式
image.png

image.png

若要获取哪个线程的哪个SyncData,需先找到下标,第一次进来后发现result有值,后面就会将*listP赋值给result->nextData


image.png

image.png

若没有线程栈存缓存SyncData的形式,则通过缓存的形式SyncCache获取
image.png

分三种情况
1.第一次进来,没有锁:两种缓存都没有,进入代码块,result->threadCount=1,进入goto done代码,result,lockCount=1存到tls里面,方便下次查找,全局栈存缓存里面也存一次
image.png
image.png

2.不是第一次,同一个线程:第二次进入在栈存缓存中能找到,lockCount++,1+1又存到栈存缓存中去

image.png

3.不是第一次,不同线程:第三次栈存缓存(新的线程3)中没有,线程3,对全局的线程空间进行查找,threadCount++和lockCount++,存到全局线程栈存cache中,之前第一步进行存储时传入的是cache = fetch_cache(YES),存储到全局栈存缓存总表中,第一次进入新建全局栈存缓存空间cache总表进行存储,宏定义_objc_pthread_key唯一,#define _objc_pthread_key TLS_DIRECT_KEY # define TLS_DIRECT_KEY ((tls_key_t)__PTK_FRAMEWORK_OBJC_KEY0)存储到分配的内存空间cache总表中唯一,第二次进行查找是传入NO不会再重新分配栈存缓存空间,能直接查找到,查找到之后进行获取item,SyncCacheItem *item = &cache->list[i]进行ACQUIRE,lockCount++,从全局栈存缓存空间中获取到cache总表进行查找遍历item,判断和当前的self是否是同一个对象,若相同,则取出第一次存的item,进行lockCount++,
image.png

image.png

image.png

image.png

image.png

此时并不会return result,而是跳入下面的代码块,对threadCount进行++操作进入done函数
image.png

lockCount的值每次存进去的时候都为1,代表总表里面的线程分表的锁住次数始终为1,每个线程的表在总表中都做一次初始化,这个值不会再变了,后面再次进来的时候,就走单个的线程缓存了不会再走总表的线程缓存了,这儿的lockCount为1和前面的lockCount++代表的不是同一个概念,前面lockCount++表示同一个线程锁住block的次数,这儿的lockCount就是总表中的子线程表的初始化lockCount为1,做个标记
image.png

封装了一把锁recursive_mutex_t,为什么可以重入重复锁,增加了lockCount,防止多线程重入,增加了threadCount
同理objc_sync_exit进行反向操作,进行release

5.@synchronize坑点:@synchronized(self) : 性能 + objc 生命周期,enter 找节点 objc : 查找非常麻烦 - self

1.性能低,链表的查询,缓存下层的代码不断的查找,锁self的节点过多,链表查询变慢

image.png

2.多线程操作数据程序崩溃:_testArray = [NSMutableArray array]相当于进行setter操作,对新值retain,对旧值进行release,某一瞬间同时两个线程对_testArray指向的区域进行release操作,但只进行了一次retain操作,retainCount只为1,不够减,形成野指针,造成崩溃

image.png

image.png

image.png

查看是否为野指针,通过添加Zombie Objects,解决办法是加锁,可以加@synchronized,若用_testArray为锁中的对象,则不能,_testArray还有可能为空,锁self是可以的,为什么呢?self持有testArray,若self释放了为nil,则testArray必定释放了,self伴随了testArray整个生命周期


image.png

image.png

image.png

image.png

还可以用NSLock进行加锁,还有其他锁的类型且看下篇文章分析


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容

  • iOS 底层原理 文章汇总[//www.greatytc.com/p/412b20d9a0f6] 本文是...
    Style_月月阅读 4,911评论 14 15
  • iOS 底层原理 文章汇总[//www.greatytc.com/p/412b20d9a0f6] 本文主...
    Style_月月阅读 4,372评论 9 16
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,523评论 16 22
  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    迷月闪星情阅读 10,564评论 0 11
  • 在妖界我有个名头叫胡百晓,无论是何事,只要找到胡百晓即可有解决的办法。因为是只狐狸大家以讹传讹叫我“倾城百晓”,...
    猫九0110阅读 3,261评论 7 3