多线程实现原理

本文详细介绍了GCD(Grand Central Dispatch)的实现原理,包括GCD的组件、使用的技术以及调度策略。通过讲解GCD如何利用libdispatch库、工作队列和内核级支持来高效管理线程,阐述了其优于传统线程管理API的优势。同时,文章还解释了多线程、上下文切换、线程问题等相关概念,并提供了GCD常用API的示例,帮助读者更好地理解和应用GCD。
摘要由CSDN通过智能技术生成

源码:https://github.com/baitxaps/Block


一、GCD实现

 1>GCD实现需要使用的一些工具:

 .用于管理追加的BlockC语言层实现的FIFO队列

 .Atomic 函数中实现的用于排他控制的轻量级信号

 .用于管理线程的C语言层实现的一些容器

 

 但是还要内核级的实现,通常,应用程序中编写的线程管理用的代码要在系统级(iOSOS X的核心级)实现

 因此,无论编程人员如何努力编写管理线程的代码,在性能方面也不能胜过XNU内核级所实现的GCD

 使用使用GCD要比使用pthreadsNSThread这些一般的多线程编程API更好,并且,如果使用GCD就不必

 编写这操作线程反复出现类似的源代码(因定源代码片断),而可以在线程中集中实现处理内容。尽量多使用

 GCD或者用Cocoa框架GCDNSOperationQueue类的API

 

 2>用于实现Dispatch Queue而使用的软件组件

 组件名称              提供技术

 libdispatch         Dispatch Queue

 libc(pthreads)      pthread_workqueue

 XUN内核              workqueue

 

 3>编程人员所使用GCDAPI全部为包含有libdispatch库的C函数,Dispatch Queue通过结构体和链表,被

 实现为FIFO队列,FIFO队列管理是通过dispatch_async()等函数所追加的Block,Block并不是直接加入FIFO

 队列,而是先加入Dispatch Continuation这一dispatch_continuation_t类型结构体中,然后再加入FIFO

 队列。Dispatch Continuation用于记忆Block所属的Dispatch Group和其他一些信息(执行上下文)

 

 4>Dispatch Queue可通过dispatch_set_target_queue()设定,可以设定执行该Dispatch Queue处理的

 Dispatch Queue为目标。该目标可像串珠子一样,设定多个连接在一起的Dispatch Queue,但是在连接串的最后

 必须设定Main Dispatch Queue,或各种优先级的Global Dispatch Queue,或是准备用于Serial Dispatch Queue

 Global Dispatch Queue

 

 5>Global Dispatch Queue8种优先级:

 .High priority

 .Default Priority

 .Low Priority

 .Background Priority

 .High Overcommit Priority

 .Default Overcommit Priority

 .Low Overcommit Priority

 .Background Overcommit Priority

附有OvercommitGlobal Dispatch Queue使用在Serial Dispatch Queue中,不管系统状态如何,都会强

 制生成线程的 Dispatch Queue

 8Global Dispatch Queue各使用1pthread_workqueue,GCD初始化时,使用pthread_workqueue_create_np()

 生成pthread_workqueue 

 pthread_workqueue使用bsdthread_registerworkq_open系统调用,在初始化XUN内核的workqueue之后获取workqueue

 信息

 

 6>XUN内核的4workqueue的优先级,与Global Dispatch Queue4种执行优先级相同

 .WORKQUEUE_HIGH_PRIQUEUE

 .WORKQUEUE_DEFAULT_PRIQUEUE

 .WORKQUEUE_LOW_PRIQUEUE

 .WORKQUEUE_BG_PRIQUEUE

 

 7>Dispatch Queue中执行Block过程

 当在Global Dispatch Queue中执行Block时,libdispatchGlobal Dispatch Queue自身的FIFO队列中取

 Dispatch Continuation,调用pthread_workqueue_additem_np(),将该Global Dispatch Queue自身、符

 合优先级的workqueue信息以及为执行Dispatch Continuation的回调函数等传递给参数。

 thread_workqueue_additem_np()使用workq_kernreturn系统调用,通知workqueue啬应当执行的项目,根据该

 通知,XUN内核基于系统状态判断是否要生成线程,如果是Overcommit优先级的Global Dispatch Queueworkqueue

 则始终生成线程。

 .该线程虽然与iOSOS X中通常使用的线程大致相同,但是有一部分pthread API不能使用

 .workqueue生成的线程在实现用于workqueue的线程计划表中运行,与一般线程的上下文切不同,这里也隐藏着使用GCD

 原因

 .workqueue的线程执行pthread_workqueue(),该函数用libdispatch的回调函数,在回调函数中执行执行加入到

 Dispatch ContinuatinBlock

 .Block执行结束后,进行通知Dispatch Group结束,释放Dispatch Continuation等处理,开始准备执行加入到Dispatch Continuation中的下一个Block

 

二、常用术语介绍

 1.多线程

 由于一个CPU一次只能执行一个命令,不能执行某处分开的并列的两个命令,因此通过CPU执行的CPU命令列就

 好比一条无分叉的大道,其执行不会出现分歧

 一个CPU执行的CPU命令列为一条无分叉路径:线程,这时无分叉路径不只1条,存在有多条时即:多线程。

 现在一个物理CPU芯片实际上有64(64)CPU,在多线程中,1CPU核执行多条不同路径上的不同命令。

 

 2.上下文切换

 1CPU核一次能够执行的CPU命令始终为1,OS XiOS的核心XUN内核在发生操作系统事件时(如每隔一定时间,

 唤起系统调用等情况)会切换执行路径。执行中路径的状态,CPU的寄存器等信息保存到各自路径专用的内存块中,

 从切换目标路径专用的内存块中,复原CPU寄存器等信息,继续执行切换路径的CPU命令列:上下文切换

 

 由于使用多线程的程序可以在某个线程和其他线程之间反复多次进行上下文切换,因些看上去就像1CPU核能够

 并列执行多个线程一样,而且在具有多个CPU核的情况下,就是真的提供了多个CPU核并行执行多个线程的技术

 

 3.多线程问题

 多线程实际上是一种易发生各种问题的编程技术,比如多个线程更新相同的资源会导致数据的不一致(数据竞争)

 停止等待事件的线程会导致多个线程相互技续等待(死锁)、使用太多线程会消耗大量内存等

 

 4.主线程

 应用程序在启动时,通过最先执行的线程。主线程来描绘用户界面、处理触摸屏幕的事件等。如果在该主线程中进行

 长时间的处理,就会妨碍主线程的执行(阻塞),OSiOS的应用程序中,会妨碍主线程中被称为RunLoop的主循环的

 执行,从面导致不能更新用户界面、应用程序的画面长时间停滞等问题

 

三、常用GCD的API例子

#pragma mark - GCDTest

- (void)GCDTest{

    //0.

    dispatch_queue_t serialDispatchQueue = dispatch_queue_create("blog.csdn.net/baitxaps"NULL);

    //1.

    dispatch_queue_t concurrentDispatchQueue = dispatch_queue_create("blog.csdn.com/baitxaps"DISPATCH_QUEUE_CONCURRENT);

    

    dispatch_async(concurrentDispatchQueue,^{

        NSLog(@"Block on concurrentDispatchQueue");

    });

    

#if !OS_OBJECT_USE_OBJC

   //dispatch_release(serialDispatchQueue);

    dispatch_release(concurrentDispatchQueue);

#endif

    

    

    //2.各种Dispatch Queue获取方法

    /*

     对于 Main Dispatch QueueGlobal Dispatch Queue执行dispatch_retaindispatch_release函数不会引用作何变化,

     也不会有任何问题

     */

    dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();//main Dispatch Queue

    dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH0);//最高优先级

    dispatch_queue_t globalDispatchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT0);//默认优先级

    dispatch_queue_t globalDispatchQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW0);//默认优先级

    dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND0);//后台优先级

  

    //3.默认优先级的Global Dispatch Queue中执行Block

    dispatch_async(globalDispatchQueueDefault, ^{

        // 并行执行的处理

        //...

        dispatch_async(mainDispatchQueue, ^{

            //只能在主线程中执行的处理

            //...

        });

        

    });

    

    //4.指定变更执行优先级(在后台执行动作处理的Serial Dispatch Queue的生成方法)

    dispatch_set_target_queue(serialDispatchQueue, globalDispatchQueueBackground);

    

    //5.在指定时间后执行处理的情况,用dispatch_after

    dispatch_time_t  time =dispatch_time(DISPATCH_TIME_NOW3ull *NSEC_PER_MSEC);

    dispatch_after(time, mainDispatchQueue, ^{

        NSLog(@"waited at least 3 seconds.");

    });

    

    //6.dispatch_walltime()

    dispatch_time_t seconds = getDispatchTimeByDate([NSDate date]);

    NSLog(@"second = %llu",seconds);

    

    //7.Dispatch Group

    dispatch_group_t group = dispatch_group_create();

    dispatch_group_async(group, globalDispatchQueueDefault, ^{ NSLog(@"blk0");});

    dispatch_group_async(group, globalDispatchQueueDefault, ^{ NSLog(@"blk1");});

    dispatch_group_async(group, globalDispatchQueueDefault, ^{ NSLog(@"blk2");});

    

    dispatch_group_notify(group, mainDispatchQueue, ^{ NSLog(@"done");});

#if !OS_OBJECT_USE_OBJC

    dispatch_release(group);

#endif

    

    //7.dispatch_group_wait()

    dispatch_group_t group_wait = dispatch_group_create();

    dispatch_group_async(group_wait, globalDispatchQueueDefault, ^{ NSLog(@"blk0");});

    dispatch_group_async(group_wait, globalDispatchQueueDefault, ^{ NSLog(@"blk1");});

    dispatch_group_async(group_wait, globalDispatchQueueDefault, ^{ NSLog(@"blk2");});

    

    dispatch_group_wait(group_wait, DISPATCH_TIME_FOREVER);

#if !OS_OBJECT_USE_OBJC

    dispatch_release(group_wait);

#endif

    

    //8.

    time = dispatch_time(DISPATCH_TIME_NOW,1ull *NSEC_PER_SEC);

    dispatch_group_t group_result = dispatch_group_create();

    long result = dispatch_group_wait(group_result, time);

   // long result = dispatch_group_wait(group_result, DISPATCH_TIME_NOW);

    if (result == 0) {

        //属于Dispatch Group的全部内容处理执行结束

    }else{

        //属于Dispatch Group的某一个处理还在执行中

    }

    

    //9.dispatch_barrier_async()

    dispatch_async(concurrentDispatchQueue, ^{ NSLog(@"blk0 for reading");});

    dispatch_async(concurrentDispatchQueue, ^{ NSLog(@"blk1 for reading");});

    dispatch_async(concurrentDispatchQueue, ^{ NSLog(@"blk2 for reading");});

    dispatch_barrier_async(concurrentDispatchQueue, ^{ NSLog(@"blk3 for writing");});

    dispatch_async(concurrentDispatchQueue, ^{ NSLog(@"blk4 for reading");});

    dispatch_async(concurrentDispatchQueue, ^{ NSLog(@"blk5 f

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值