使用 GCD 的 dispatch queue 实现同步锁

来源:互联网 发布:dnspod 阿里云 编辑:程序博客网 时间:2024/06/07 20:24

同步锁的实现方案有不少,比如,如果仅仅是想对某个实例变量的读写操作加锁,可以使用属性(property)的 atomic 参数,对于一段代码加锁可以使用 @synchronized 块,或者 NSLock。

@synchronized 和 NSLock 实现的同步锁:

// Method 1- (void)synchronizedMethod {    @synchronized(self) {        // safe    }}// Method 2_lock = [[NSLock alloc] init];- (void)synchronizedMethod {    [_lock lock];    // Safe    [_lock unlock];}

@synchronized 一般会以 self 为同步对象。重复调用 @synchronized(self) 是很危险的。如果多个属性这么做,每一个属性将会被和其它所有属性同步,这可能并不是你所希望的,更好的方法是每个属性的锁都是相互独立的。

另一种方法是使用 NSLock 实现同步锁,这个方法不错,但是缺点是在极端环境下同步块可能会导致锁死,而且这种情况下处理锁死状态会有麻烦。

一个替代方法是使用 GCD 的分发队列。将读和写分发到相同并发队列中,这样读操作会是并发的,多个线程可以同时执行写操作;而对于写操作,以分发栅栏(dispatch barrier)保证同时只有一个线程可以执行写操作,并且由于写操作无需返回,写操作还是异步马上返回的。这样,就得到了一个高效且线程安全的锁。代码看起来会像这样:

_syncQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);- (NSInteger)cake {    __block NSInteger localCake;    dispatch_sync(_syncQueue, ^{        localCake = _cake;    });    return localCake;}- (void)setCake:(NSInteger)cake {    dispatch_barrier_async(_syncQueue, ^{        _cake = cake;  });}

简单而言,上面的代码可以使读操作被竞争执行;写操作被互斥执行,并且异步返回。使用 GCD 实现的这个同步锁应该是效率最优且最安全的。


参考http://www.infoq.com/cn/articles/os-x-ios-multithread-technology

0 0
原创粉丝点击