编写高质量代码的52个有效方法

52个有效方法(41) - 多用派发队列,少用同步锁

2018-09-28  本文已影响7人  SkyMing一C

在Objective-C中,如果有多个线程要执行同一份代码,那么有时可能会出问题。这种情况下,通常要使用锁来实现某种同步机制。

- (void)synchronizedMethod
{
    @synchronized (self) {
        //Safe
    }
}
_lock = [[NSLock alloc]init];

- (void)synchronizedMethod
{
    [_lock lock];
    //Safe
    [_lock unlock];
}

这两种都会遇到死锁现象。而且其效率并不高。

GCD

_syncQueue = dispatch_queue_create("com.effectiveobjectivec.syncQueue", NULL);

- (NSString *)someString
{
    __block NSString *localSomeString;
   dispatch_sync(_syncQueue, ^{
    localSomeString = self.someString;
    });
    return localSomeString;
}


- (void)setSomeString:(NSString *)someString
{
    dispatch_sync(_syncQueue, ^{
        self.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;
        });
}
void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block);

void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
在这个并发队列中,读取操作使用普通的块来实现的,而写入操作则是用栅栏块来实现的。读取操作可以并行,但写入操作必须单独执行,因为他是栅栏块

设置方法中使用了栏栅块之后,对属性的读取操作依然可以并发执行,但是写入操作却必须单独执行了。

- (void)setSomeString:(NSString *)someString
{
   dispatch_barrier_async(_syncQueue, ^{
       self.someString = someString;
  });
}
要点
  1. 派发队列可用来表述同步语义(synchronization semantic),这种做法要比使用@synchronized块或NSLock对象更简单。

  2. 将同步与异步派发结合起来,可以实现与普通加锁机制一样的同步行为,而这么做却不会阻塞执行异步派发的形成。

  3. 使用同步队列及栅栏块,可以令同步行为更加高效。

上一篇 下一篇

猜你喜欢

热点阅读