GCD多线程的使用(二)
记录一下GCD的几个重要API的用法。
dispatch_queue_create
* @param label * A string label to attach to the queue. * This parameter is optional and may be NULL. * * @param attr * DISPATCH_QUEUE_SERIAL or DISPATCH_QUEUE_CONCURRENT. * * @result * The newly created dispatch queue. dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
用来创建Dispatch Queue,返回值类型是dispatch_queue_t,这个方法需要传递两个参数,label是附加到queue上的一个字符串标签,这个参数是可选的,并且有可能为空,这是queue的名字,在进行调试的时候会很方便,所以推荐在创建Dispatch Queue的时候传一个标签。获取一个queue的名字的方法如下:
/*! * @function dispatch_queue_get_label * * @abstract * Returns the label of the given queue, as specified when the queue was * created, or the empty string if a NULL label was specified. * * Passing DISPATCH_CURRENT_QUEUE_LABEL will return the label of the current * queue. * * @param queue * The queue to query, or DISPATCH_CURRENT_QUEUE_LABEL. * * @result * The label of the queue. */ const char * dispatch_queue_get_label(dispatch_queue_t queue);
第二个参数attr是用来指定创建的Dispatch Queue的类型,DISPATCH_QUEUE_SERIAL或者NULL表示创建串行Dispatch Queue,DISPATCH_QUEUE_CONCURRENT表示创建并行Dispatch Queue。其实创建串行的参数DISPATCH_QUEUE_SERIAL就是NULL,源码如下:
/*! * @const DISPATCH_QUEUE_SERIAL * @discussion A dispatch queue that invokes blocks serially in FIFO order. */ #define DISPATCH_QUEUE_SERIAL NULL
FIFO,即First in first out,先进先出。
关于创建的两种Dispatch Queue类型,Serial Dispatch Queue同时只能执行一个追加处理,Concurrent Dispatch Queue能并行追加多个处理,虽然这两种Dispatch Queue受到系统资源的限制,但用dispatch_queue_create函数可以生成任意多个Dispatch Queue。当生成多个Serial Dispatch Queue时,各个Serial Dispatch Queue并行执行,虽然在一个Serial Dispatch Queue中同时只能执行一个追加处理,但如果将处理分别追加到4个Serial Dispatch Queue中,各个Serial Dispatch Queue执行一个,即同时执行4个处理。也就是一旦生成Serial Dispatch Queue并进行追加处理,系统就要对这个Serial Dispatch Queue生成且只生成一个线程,如果生成多个Serial Dispatch Queue,那么系统就生成多个线程。
虽然能生成多个线程,但是决不能滥用Serial Dispatch Queue,因为如果过多的使用线程,会消耗大量的内存,引起大量的上下文切换,大幅度降低系统的响应性能。所以建议只在为了避免多个线程更新相同资源导致数据竞争时使用Serial Dispatch Queue。
当想并行执行不发生数据竞争问题的处理时,使用Concurrent Dispatch Queue,对于Concurrent Dispatch Queue来说,不管生成多少,由于XNU内核只使用有效管理的线程,因此不会发生Serial Dispatch Queue的那些问题。
另外,通过diaptch_queue_create函数生成的Dispatch Queue在使用结束后需要通过dispatch_release函数来释放。
dispatch_release(queue);
相对应的,GCD也有retain操作,dispatch_retain函数就是增加引用计数的。GCD中得Dispatch Queue也像Objectiv-C的引用技术式内存管理一样,需要通过dispatch_retain和dispatch_release的引用计数来管理内存。
最后推荐一个非常好的博客:唐巧的技术博客。