Dispatch Semaphore & NSCondition

dispatch_semaphore 使用 http://www.cnblogs.com/snailHL/p/3906112.html

两个作用

加锁/数据同步

dispatch_semaphore_create

dispatch_semaphore_signal

dispatch_semaphore_wait

1
2
3
- (void)methodWithABlock:(DHBLK)blk{
blk(@"hahaha");
}

测试代码1 单个block

1
2
3
4
5
6
7
8
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[self methodWithABlock:^(id result){
//写block中做的事情
//结束等待
dispatch_semaphore_signal(sem);
}];
//等待信号
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

测试代码2 多个 blcok

xxx.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[self methodWithABlock:^(id result){
//写block中做的事情
dispatch_semaphore_signal(sem);
[self methodWithABlock:^(id result){
//写block中做的事情
dispatch_semaphore_signal(sem);
}];
}];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

测试代码3

1
2
3
4
5
6
7
8
9
10
11
12
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int j = 0;
dispatch_async(queue, ^{
j = 100;
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"%d",j);
// j = 100

测试代码 4 加锁测试 ,反注释掉//

1
2
3
4
5
6
7
8
for (int i = 0; i < 100; i++) {
dispatch_async(queue, ^{
// 相当于加锁
// dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"i = %zd semaphore = %@", i, semaphore);
// 相当于解锁
// dispatch_semaphore_signal(semaphore);
});

NSCondition 的使用

NSCondition 的对象实际上作为一个锁和一个线程检查器:锁主要为了当检测条件时保护数据源,执行条件引发的任务;线程检查器主要是根据条件决定是否继续运行线程,即线程是否被阻塞。
http://www.jianshu.com/p/5d20c15ae690

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
NSCondition *condition = [[NSCondition alloc] init];
__block NSMutableArray *products = [[NSMutableArray alloc] initWithCapacity:10];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[condition lock];
while ([products count] == 0) {
NSLog(@"wait for products ");
[condition wait];
}
[products removeObjectAtIndex:0];
NSLog(@"custome a product");
[condition unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[condition lock];
products = [NSMutableArray array];
[products addObject:@"oo"];
NSLog(@"produce a obj");
[condition signal];
[condition unlock];
});

异步下载图片完成后同步完成数据库再通知UI刷新的机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
- (void)receiveMessage:(MessageEntity *)message
{
NSCondition *condition = [[NSCondition alloc]init];
[condition lock];
NSInteger imageCount ;
void(^unlock)=^(){
while(!imageCount)
[condition signal];
}
imageCount++;
dowanloadImageFinished:^(UIImage *image){ //异步下载图片,下载完成的回调中
imageCount--;
unlock();
}
while(imageCount){
[condition wait];
}
[condition unLock];
}

以GPUImage 实现的延时摄影

用 semaphore 来筛选(关断)出时间间隔的图像 buffter.筛选出来的buffer 再筛入 WriterInputPixelBufferAdaptor.

https://github.com/yangfangxue/GPUImageRecord.git

1.dispatch timer 的用法

1
2
3
4
5
6
7
8
9
10
__weak typeof(self) ws =self;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), 0.5 * NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(_timer, ^{
[ws defaultTimerHandel];
});
_seam = dispatch_semaphore_create(0);

//使用 timer 和销毁

1
2
3
dispatch_resume(_timer);
dispatch_cancel(_timer);

GPUImageVideoCamera 中回调方法CMSampleBufferRef的 lock

1
2
3
4
5
6
7
[_camera addTarget:self.preview];
//获取buffer
CVPixelBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer, 0);
_imageBuffer = CVPixelBufferRetain(imageBuffer);
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);

录制配置路径的时候需要检测是否存在,清除历史文件

完成录制时候加入condition 保护

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[writerInput markAsFinished];
if(videoWriter.status == AVAssetWriterStatusWriting){
NSCondition *cond = [[NSCondition alloc] init];
[cond lock];
[videoWriter finishWritingWithCompletionHandler:^{
[cond lock];
[cond signal];
[cond unlock];
}];
[cond wait];
[cond unlock];
[self savePhotoCmare:self.url];
}