标签:"gcd"

GCD外传:dispatch_once(下)

在本系列前两篇文章中,我们一起学习了dispatch_once的作用、工作原理以及效率研究:dispatch_once使得block中的代码执行且只执行一次,在多线程竞态时,使其他线程进入等待状态直至block执行完毕,并且还保证无竞态时执行效率与非线程安全的if语句效率相当。dispatch_once内部使用了大量的原子操作来替代锁与信号量,这使得其效率大大提升,但带来的是维护和阅读性的降低。dispatch_once被大量使用在构建单例上,apple也推荐如此。但是我们可能会有两个疑问:使用dispatch_once实现的单例,在初始化后,难以简单做到反初始化或者重初始化,如何解决?使用dispatch_once时,static predicate一定程度限制了dispatch_once的使用场景,又如何解决。 本篇我们一起探究使用非static predicate的可能性,在后续系列文章中,我还将和大家一起探讨如何安全地重置predicate。一、文档参考如果查阅dispatch_once函数文档,对于predicate,文档有如下说明:The predicate must point to a variable stored in global

GCD外传:dispatch_once(中)

本篇,我将和大家一起探究dispatch_once写入端的实现
让我们先看看dispatch_once的实现(Grand Central Dispatch是开源的,大家可以到github上面下载源码)
struct _dispatch_once_waiter_s {
volatile struct _dispatch_once_waiter_s *volatile dow_next;
_dispatch_thread_semaphore_t dow_sema;
};

#define DISPATCH_ONCE_DONE ((struct _dispatch_once_waiter_s *)~0l)

#ifdef __BLOCKS__
void
dispatch_once(dispatch_once_t *val, dispatch_block_t block)
{
struct Block_basic *bb = (void *)block;

dispatch_once_f(val, block, (void *)bb->Block_invoke);
}
#endif

DISPATCH_NOINLINE
void
dispatch_once_f(dispatch_once_t *val, void *ctxt, dispatch_function_t func)
{
struct _dispatch_once_waiter_s * volatile *vval = (struct _dispatch_once_waiter_s**)val;
struct _dispatch_once_waiter_s dow = { NULL, 0 };
struct _dispatch_once_waiter_s *tail, *tmp;
_dispatch_thread_semaphore_t sema;

if

GCD外传:dispatch_once(上)

相信大家对dispatch_once都不陌生了,这一篇我将和大家一起探究dispatch_once的更多细节。 dispatch_once的作用正如其名:对于某个任务执行一次,且只执行一次。 dispatch_once函数有两个参数,第一个参数predicate用来保证执行一次,第二个参数是要执行一次的任务block。

GCD实战练习:资源竞争

概述
我将分四步来带大家研究研究程序的并发计算。第一步是基本的串行程序,然后使用GCD把它并行计算化。 
原始程序
我们的程序只是简单地遍历~/Pictures然后生成缩略图。这个程序是个命令行程序,没有图形界面(尽管是使用Cocoa开发库的),主函数如下:

int main(int argc,

GCD(Grand Central Dispatch)教程

Grand Central Dispatch或者GCD,是一套低层API,提供了一种新的方法来进行并发程序编写。从基本功能上讲,GCD有点像NSOperationQueue,他们都允许程序将任务切分为多个单一任务然后提交至工作队列来并发地或者串行地执行。GCD比之NSOpertionQueue更底层更高效,并且它不是Cocoa框架的一部分。

GCD入门(四): 完结

Dispatch Queue挂起
dispatch queue可以被挂起和恢复。使用 dispatch_suspend函数来挂起,使用  dispatch_resume 函数来恢复。这两个函数的行为是如你所愿的。另外,这两个函数也可以用于dispatch source。
一个要注意的地方是,dispatch queue的挂起是block粒度的。换句话说,挂起一个queue并不会将当前正在执行的block挂起。它会允许当前执行的block执行完毕,然后后续的block不再会被执行,直至queue被恢复。
还有一个注意点:从man页上得来的:如果你挂起了一个queue或者source,那么销毁它之前,必须先对其进行恢复。

GCD入门(三): Dispatch Sources

何为Dispatch Sources
简单来说,dispatch source是一个监视某些类型事件的对象。当这些事件发生时,它自动将一个block放入一个dispatch queue的执行例程中。
说的貌似有点不清不楚。我们到底讨论哪些事件类型?
下面是GCD 10.6.0版本支持的事件:

GCD入门(二): 多核心的性能

概念
为了在单一进程中充分发挥多核的优势,我们有必要使用多线程技术(我们没必要去提多进程,这玩意儿和GCD没关系)。在低层,GCD全局dispatch queue仅仅是工作线程池的抽象。这些队列中的Block一旦可用,就会被dispatch到工作线程中。提交至用户队列的Block最终也会通过全局队列进入相同的工作线程池(除非你的用户队列的目标是主线程,但是为了提高运行速度,我们绝不会这么干)。
有两种途径来通过GCD“榨取”多核心系统的性能:将单一任务或者一组相关任务并发至全局队列中运算;将多个不相关的任务或者关联不紧密的任务并发至用户队列中运算;
全局队列
设想下面的循环:

GCD入门(一): 基本概念和Dispatch Queue

什么是GCD?
Grand Central Dispatch或者GCD,是一套低层API,提供了一种新的方法来进行并发程序编写。从基本功能上讲,GCD有点像NSOperationQueue,他们都允许程序将任务切分为多个单一任务然后提交至工作队列来并发地或者串行地执行。GCD比之NSOpertionQueue更底层更高效,并且它不是Cocoa框架的一部分。
除了代码的平行执行能力,GCD还提供高度集成的事件控制系统。可以设置句柄来响应文件描述符、mach ports(Mach port 用于 OS X上的进程间通讯)、进程、计时器、信号、用户生成事件。这些句柄通过GCD来并发执行。
GCD的API很大程度上基于block,当然,GCD也可以脱离block来使用,比如使用传统c机制提供函数指针和上下文指针。实践证明,当配合block使用时,GCD非常简单易用且能发挥其最大能力。