学计算机的那个

不是我觉到、悟到,你给不了我,给了也拿不住;只有我觉到、悟到,才有可能做到,能做到的才是我的.

0%

【读书笔记】OC高级编程多线程和内存管理

GCD几个重要的函数

几个重要方法

dispatch_block_create_with_qos_class

将 GCD 的 block 通过 dispatch_block_create_with_qos_class 方法指定队列的 QoS 为 QOS_CLASS_UTILITY。这种 QoS 系统会针对大的计算,I/O,网络以及复杂数据处理做电量优化。

dispatch_set_target_queue
设置队列的 QoS 或者优先级和另一个队列一样

创建队列的层次体系。当我们想让不同队列中的任务同步的执行时,我们可以创建一个串行队列,然后将这些队列的 target 指向新创建的队列

Serial Dispatch Queue

系统对于一个Serial Dispatch Queue就只生成并使用一个线程。(所以4个SerialDispatchQueue 性能比一个concurrent queue里的4个block任务 更消耗内存,会引起大量上下文切换,大幅度降低系统的响应性能)。

使用场景:
多个线程更新相同资源导致数据竞争时使用 Serial Dispatch Queue

Concurrent dispatch queue

当想并行执行不发生数据竞争等问题处理时,使用concurrent dispatch queue

注意:
通过dispatch_queue_create的 dispatch_queue_t对象需要自己管理内存,dispatch_release

1
2
3
4
5
6
7
8
9
10
//eg    YYWebImage
+ (dispatch_queue_t)setterQueue {
static dispatch_queue_t queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
queue = dispatch_queue_create("com.ibireme.webimage.setter", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
});
return queue;
}

Global Dispatch Queue 4种优先级

High > Default > Low > Background

dispatch_set_target_queue

dispatch_queue_create函数生成的Dispatch_queue不管是Serial还是concurrent都使用与默认优先级Global dispatch queue相同执行优先级的线程。而变更生成的dispatch queue的执行优先级要使用dispatch_set_target_queue函数。

dispatch_after

1
2
3
4
5
//e.g. 
dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW,3ull* NSEC_PEC_SEC);
dispatch_after(time,dispatch_get_main_queue(),^{
NSLog(@“waited at least three seconds.”);
});

dispatch_after并不是在指定时间后执行,而只是在指定时间追加处理到Dispatch Queue,上面代码与在3秒后用dispatch_async函数追加Block到main Dispatch Queue的相同。

因为Main Dispatch Queue在线程的Runloop中执行,所以在比如每隔1/60秒执行的Runloop中,Block最快在3秒后执行,最慢在3秒+1/60秒后执行。

DISPATCH_TIME_NOW 表示现在的时间

dispatch_group_wait(group,time);

1
2
3
4
5
6
7
8
9
10
11
//e.g.
dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW,1null*NSEC_PEC_SEC);
long result=dispatch_group_wait(group,time);
if(result==0)
{
//属于dispatch group的全部处理执行结束
}
else
{
//属于Dispatch Group的某一个处理还在执行中
}

这里的等待会卡住当前线程,直到 指定的时间到了或者dispatch group的处理全部执行结束后。

dispatch_barrier_async

该函数同dispatch_queue_create 函数生成的 Concurrent Dispatch Queue一起使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dispatch_queue_t  queue=dispatch_queue_create(“com.example.gcd.ForBarrier”,DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue,blk0_for_reading);
dispatch_async(queue,blk1_for_reading);
dispatch_async(queue,blk2_for_reading);
dispatch_async(queue,blk3_for_reading);
dispatch_async(queue,blk4_for_reading);

dispatch_barrier_async(queue,blk_for_writing);

dispatch_async(queue,blk5_for_reading);
dispatch_async(queue,blk6_for_reading);
dispatch_async(queue,blk7_for_reading);
dispatch_async(queue,blk8_for_reading);
dispatch_release(queue);

使用concurrent dispatch queue和 dispatch_barrier_async函数可实现高效率的数据库访问和文件访问。

Dispatch Semaphore

Dispatch Semaphore是持有计数的信号,该计数是多线程编程中的技术类型信号。技术为0时等待,计数为1或大于1时,减去1而不等待。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//创建一个信号量,初始值为1
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1) ;
NSMutableArray *array = [[NSMutableArray alloc] init];
for(int i = 0; i< 1000; ++i) {
dispatch_async(queue, ^{
//这里会一直等待,直到信号量大于等于1,对改计数进行减法,并返回
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) ;


NSLog(@"%@",[NSThread currentThread]);
[array addObject:[NSNumber numberWithInt:i]];

//这里增加一个信号量
dispatch_semaphore_signal(semaphore);
});
}

dispatch_semaphore_t 信号量本质上是一种锁