GCD简单分析
GCD:Grand Central Dispatch,纯C语言,是Apple公司为多核的并行运算提出的解决方案
GCD会自动利用更多的CPU内核(比如双核、四核)
GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
dispatch_queue_t:调度队列
DISPATCH_QUEUE_SERIAL(NULL):串行队列标识
创建串行队列:dispatch_queue_t serial = dispatch_queue_create("car", DISPATCH_QUEUE_SERIAL);
DISPATCH_QUEUE_CONCURRENT:并行队列
创建并行队列:dispatch_queue_t conque = dispatch_queue_create("car", DISPATCH_QUEUE_CONCURRENT);
创建主队列: dispatch_queue_t mainQueue = dispatch_get_main_queue();
系统并行队列: dispatch_queue_t globQueue = dispatch_get_global_queue(0, 0);
异步:dispatch_async
特点:不用等待当前语句执行完毕,就可以执行下一条语句、会开启线程执行block的任务
同步:dispatch_sync
特点:必须等待当前语句执行完毕才会执行下一条语句、不会开启线程、在当前执行的block
图(1) 图(2) 图(3)由上面的截图可以看出,异步线程在串行和并发队列中是先执行,然后才到主线程
图(4)由上面的截图可以看出,异步线程在主队列中是先执行主线程,在到异步线程中执行
图(5) 图(6) 图(7)由上面的截图可以看出,同步线程在串行和并发队列中是先执行,然后才到主线程
图(8)由上面的截图可以看出,同步线程在主队列中是死锁。
把任务添加到队列中:
图(9)函数与队列:
图(10)主队列与全局队列:
主队列(dispatch_get_main_queue()):在主线程上调度任务的串行队列、不会开启线程。如果当前主线程正在执行任务,那么无论主队列中当前添加了什么任务,都不会被调度。
全局并发队列dispatch_get_global_queue(0, 0) :是一个并发队列,在多线程开发时,如果队列没有特殊需求,在执行异步任务时,可以直接使用全局队列。
死锁现象:主线程因为你同步函数的原因等着先执行任务,主队列等着主线程的任务执行完毕过后才执行自己的任务,主队列和主线程相互等待会造成死锁。
栅栏函数(dispatch_barrier_async、dispatch_barrier_sync):控制任务执行顺序,前面的任务执行完成才会来到这里,dispatch_barrier_sync会堵塞线程,影响后面的程序执行,只能控制同一并发队列。
图(11) 图(12) 图(13)信号量dispatch_semaphore_t:
图(14)Dispatch_Source:
图(15) 图(16)锁的归类:
自旋锁:线程反复检查锁变量是否可用。由于线程在这一过程保持执行,因此是一种忙等待,一旦获取自旋锁,线程就会保持该锁,直至释放自旋锁,自旋锁避免了进程上下文的调度开销,因此对于线程只会阻塞很短时间的场合是有效的。
互斥锁:(NSLock、pthread_mutex、@synchronized)是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写机制,该目的通过将代码切成一个一个的灵界区而达成。
条件锁:(NSCondition、NSConditionLock)就是条件变量,当进程的某些资源要求不满足时进入休眠就锁住了,当资源被分配到了,条件锁打开,进程继续
递归锁:(NSRecursiveLock、pthread_mutex(recursive))就是同⼀个线程可以加锁N次⽽不会引发死锁。
信号量(semaphore):(dispatch_semaphore)是⼀种更⾼级的同步机制,互斥锁可以说是semaphore在仅取值0/1时的特例。信号量可以有更多的取值空间,⽤来实现更加复杂的同步,⽽不单单是线程间互斥。
读写锁:
图(17) 图(18)锁的性能数据:
图(19)