Effective Objective-C 2.0

📚Effective OC - Tip41 多用派发队列,少用同

2017-01-11  本文已影响10人  小万叔叔

少用@synchronized self 方法

//case 1 : @synchoronized self
//这样做,只要访问self,就会被锁,抢夺同一个锁,效率级低,还不如直接atomic 属性呢
- (void)setLockerStr:(NSString *)lockerStr {
    @synchronized (self) {
        _lockerStr = lockerStr;
    }
}
- (NSString *)lockerStr {
    __block NSString* blockStr;
    @synchronized (self) {
        blockStr = _lockerStr;
    }
    return blockStr;
}

//NSLock
- (void)setLockerStr:(NSString *)lockerStr {
    [_lock lock];
    _lockerStr = lockerStr;
    [_lock unlock];
}

- (NSString *)lockerStr {
    NSString* localStr;
    [_lock lock];
    localStr =  _lockerStr;
    [_lock unlock];
    return localStr;
}

使用串行同步方法,而不是主动调用锁

//但是使用同步块,会调用拷贝block,在性能上也许不如直接锁
_syncQueue = dispatch_queue_create("syncQueue", nil);
- (void)setLockerStr:(NSString *)lockerStr {
    dispatch_sync(_syncQueue, ^{
        _lockerStr = lockerStr;
    });
}
- (NSString *)lockerStr {
    __block NSString* blockStr;
    dispatch_sync(_syncQueue, ^{
        blockStr = _lockerStr;
    });
    return blockStr;
}

如果改为并行呢,读可以多并行,而只有写是阻塞的呢

/**
    dispatch_barrier_sync
  dispatch_barrier_async
    栅栏 block 必须单独执行,不能与其他块并行,只对并行队列有意义,因为串行队列的块总是按顺序来逐个执行的
  这里再次说明下, sync 和 async 是决定是否阻塞当前线程,而决定执行是否并行,是由所放的队列来决定的
  写方法表示,可以放到并行操作里面去写,但是由于 barrier 的特性,当前的 block 一定会再前面操作之后执行,像
一道栅栏一样横在哪里, 而读操作,由于要得到接口,所以是阻塞当前线程的,但是实际多线程里面却是并行操作的。
 
     并发队列
 | Read Read
 | Read Read Read
 | Write(barrier)
 | Read Read
 |
 ⤵️
时序
*/
- (void)setLockerStr:(NSString *)lockerStr {
    dispatch_barrier_async(_asyncQueue, ^{
        _lockerStr = lockerStr;
    });
}
- (NSString *)lockerStr {
    __block NSString* blockStr;
    dispatch_barrier_sync(_asyncQueue, ^{
        blockStr = _lockerStr;
    });
    return blockStr;
}
上一篇 下一篇

猜你喜欢

热点阅读