GCD 原理
-将一段(Block)代码作为特定任务,放到指定的队列(queue:Serial(串行,同时只能执行一个任务)/globel(并行,同时可执行多个任务,但执行顺序是随机的)/main(全局的Serial,在主线程里面执行任务) dispatch queue)里,进行同步/异步(dispatch_sync/dispatch_async)处理。根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。dispatch_sync/dispatch_async的意思就是将任务进行同步/异步并行处理,不一定需要一个任务处理完后才能处理下一个
-一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。
GCD 概述
1. GCD 包含于 libSystem.dylib
2. 可供所有程序使用.
- #include <dispatch/dispatch.h>
3. GCD API 提供 block-based and function-based variants
- 目前仅提供 block-based API
GCD总结
1. Blocks
- dispatch_async()
2. Queues
- Lightweight list of blocks
- Enqueue/dequeue is FIFO
-dispatch queue分为下面三种:
-Serial 又称为private dispatch queues,同时只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。
-Concurrent 又称为global dispatch queue,可以并发地执行多个任务,但是执行完成的顺序是随机的。
-Main dispatch queue 它是全局可用的serial queue,它是在应用程序主线程上执行任务的。
3. dispatch_get_main_queue()
- Main thread/main runloop(获取主线程的队列)
4. dispatch_queue_create()
- Automatic helper thread, private dispatch queues
GCD的好处
1. 高效 - More CPU cycles available for your code
2. 使用方便
- Blocks are easy to use
- Queues are inherently producer/consumer
3. Systemwide perspective
- Only the OS can balance unrelated subsystems
兼容性
1. Existing threading and synchronization primitives are 100% compatible
2. GCD threads are wrapped POSIX threads
- Do not cancel, exit, kill, join, or detach GCD threads
3. GCD reuses threads
- Restore any per-thread state changed within a block
多线程
Session 206已提到此内容。
锁定资源
1. 对关键资源进行互斥访问。
2. 在线程中按序访问共享资源。
3. Ensure data integrity
没有GCD的代码
- (void)updateImageCacheWithImg:(UIImage*)img
{
NSLock *nLock = self.imageCacheLock;
[nLock lock];
// Critical section
if ([self.imageCache containsObj:img])
{
[nLock unlock]; // Don't forget to unlock
return;
}
[self.imageCache addObj:img];
[nLock unlock];
}
GCD代码
- (void)updateImageCacheWithImg:(NSImage*)img
{
dispatch_queue_t queue = self.imageCacheQueue;
dispatch_sync(queue, ^{ //You can change dispatch_sync to dispatch_async to defer critical section
// Critical section
UIImage *cellImage = [self loadMyImageFromNetwork:image_url];
// 将图片cache到本地
[self cacheImage:cellImage];
if ([self.imageCache containsObj:cellImage]) {
return;
}
[self.imageCache addObj:cellImage];
});
}
dispatch_sync/dispatch_async的意思就是将任务进行同步/异步并行处理,不一定需要一个任务处理完后才能处理下一个。以上代码loadMyImageFromNetwork的意思就是从网络中读取图片,这个任务交给network_queue来处理。这样读取图片的时间过长也不会阻塞主线程界面的处理。
- dispatch_async(network_queue, ^{
- UIImage *cellImage = [self loadMyImageFromNetwork:image_url];
- // 将图片cache到本地
- [self cacheImage:cellImage];
- // 回到主线程
- dispatch_async(dispatch_get_main_queue(), ^{
- // 显示图片到界面
- [self displayImageToTableView:cellImage];
- }];
- } );
- 线程间通信
通过以下方法 (Without GCD)
– performSelectorOnMainThread:withObject:waitUntilDone:
– performSelector:onThread:withObject:waitUntilDone:
– performSelector:withObject:afterDelay:
– performSelectorInBackground:withObject:
GCD 代码,等同于 performSelector:onThread:withObject:waitUntilDone:
// waitUntilDone: NO
dispatch_async(queue, ^{
[myObject doSomething:foo withData:bar];
});
// waitUntilDone: YES
dispatch_sync(queue, ^{
[myObject doSomething:foo withData:bar];
});
GCD代码, 等同于 performSelector:withObject:afterDelay:
dispatch_time_t delay;
delay = dispatch_time(DISPATCH_TIME_NOW, 50000 /* 50μs */);
dispatch_after(delay, queue, ^{ [myObject doSomething:foo withData:bar];});
GCD代码,等同于 performSelectorInBackground:withObject:
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{ [myObject doSomething:foo withData:bar];});
Global Queues
1. Enqueue/dequeue is FIFO
2. Concurrent execution- Non-FIFO completion order
3. dispatch_get_global_queue(priority, 0)
4. Global queues map GCD activity to real threads
5. Priority bands- DISPATCH_QUEUE_PRIORITY_HIGH - DISPATCH_QUEUE_PRIORITY_DEFAULT - DISPATCH_QUEUE_PRIORITY_LOW
下面三节讲述了很多内容,但我还没有理解。如有兴趣,请看原始视频。- Dispatch Sources
- Source Cancellation- Target Queues
GCD对象
GCD方法大全
管理对象的生命周期
1. Ensure objects captured by blocks are valid when blocks are executed
- Objects must be retained and released around asynchronous operations
2. Objective-C objects captured by blocks are auto-retained and auto-released
3. Other objects captured by blocks must be retained by your code
- CFRetain()/CFRelease()
- dispatch_retain()/dispatch_release()
挂起和恢复
1. Suspend and resume only affects queues and sources you create
- Sources are created suspended
2. Suspension is asynchronous
- Takes effect between blocks
3. Your queues can predictably suspend objects that target them
程序上下文
1. Applications can attach custom data to GCD objects
- dispatch_set_context()/dispatch_get_context()
2. Optional finalizer callback
- dispatch_set_finalizer_f()
- Allows attached context to be freed with object
- Called on the target queue of the object
WWDC2010 Session211 Simplifying iPhone App Development with Grand Central Dispatch
Daniel Steffen - Core OS