您的位置:首页 > 移动开发 > Objective-C

多用派发队列,少用同步锁

2016-07-29 09:01 309 查看

在Objective-C中,如果有多个线程要执行同一份代码,那么有时候可能会出现问题,这种情况下,通常使用锁来实现某种同步机制。在GCD出现之前,有两种办法。第一种采用内置的“同步块”(synchronization block):

- (void)synchronizedMethod {
@synchronized(self){
// Safe
}
}


这种写法会根据给定的对象,自动创建一个锁,并等待块中的代码执行完毕。执行到这段代码的结尾处,锁就释放了。but滥用@synchronized(self)则会降低代码效率,因为共用同一个锁的那些同步块,都必须按顺序执行。

另一个办法是直接食用NSLock对象:

_lock = [[NSLock alloc] init];
-(void)synchronizedMethod {
[_lock lock];
// Safe
[_lock unlock];
}


GCD以更简单、更高效的形式为代码加锁。 使用“串行同步队列”。将读取操作以及写入操作都安排在同一个队列里,即可保证数据同步。

_syncQueue = dispatch_queue_create("com.effectiveobjectivec.syncQueue",NULL);
- (NSString *)someString {
__block NSString *localSomething;
dispatch_sync(_syncQueue, ^{
localSomeString = _someString;
});
return localSomeString;
}
- (void)setSomeString:(NSString *)someString {
dispatch_sync(_syncQueue, ^{
_someString = someString;
});
}


多个获取方法可以并发执行,而获取方法与设置方法之间不能并发执行,利用这个特点,可以优化代码。改为并发队列。

_syncQueue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
-(NSString *)someString {
__block NSString *localSomeString;
dispatch_sync (_syncQueue, ^{
localSomeString = _someString;
});
return localSomeString;
}
- (void)setSomeString:(NSString *)someString {
dispatch_barrier_async(_syncQueue, ^{
_someString = someString;
});
}


栏栅块必须单独执行,不能与其他块并行,这只对并发队列有意义,因为串行队列中的块总是按顺序逐个来执行的。并发队列如果发现接下来要处理的块是个栏栅块,那么就一直等到当前所有并发块都执行完毕,才会单独执行这个栏栅块。待栏栅块执行过后,再按正常方式继续向下处理。

设置方法中使用了栏栅块之后,对属性的读取操作依然可以并发执行,但是写入操作却必须单独执行了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  objective-c 线程 gcd