谈谈OC优雅的使用dispatch_semaphore锁

406 阅读1分钟

背景

   OC中有八大锁,其中dispatch_semaphore性能消耗相对比较低,因此我们开发中常用的互斥锁为dispatch_semaphore。项目中多个地方用到锁都需要一些繁杂的初始化操作,为了让我们更简单、高效的开发,于是我探索关于锁的使用,提高开发效率、提升代码一致性与可读性。

如何使用

使用分为两步:① 导入头文件 ② 使用加锁解锁代码

通常情况下,导入头文件在全局导入(即 pch 文件)

#import "NSObject+Semaphore.h"
// 第一种用法,在临界区两端加上  加锁和解锁 代码
SemaphoreLock
// ...... this is your critical code ......
SemaphoreUnlock

// 第二种用法,使用 block 方式将临界区代码传入
SemaphoreAutoLock(self, ^{
// ...... this is your critical code ......
});

// 第三种用法,不推荐使用,因为这样写不知道其内部使用了哪种锁
[self Lock]
// ...... this is your critical code ......
[self Unlock]

具体实现

  • 定义OC分类,其头文件NSObject+Semaphore.h内容为:
#import <Foundation/Foundation.h>

#define SemaphoreLock [self Lock];
#define SemaphoreUnlock [self Unlock];

NS_ASSUME_NONNULL_BEGIN
typedef void (^SemaphoreLockBlock) (void);
/// 通过 Block 方式加锁
extern void SemaphoreAutoLock(NSObject * target, SemaphoreLockBlock block);


@interface NSObject (Semaphore)

/// 加锁, 内部定义了 dispatch_semaphore_create(1)
- (void)Lock;

/// 解锁, 内部定义了 dispatch_semaphore_create(1)
- (void)Unlock;

@end

NS_ASSUME_NONNULL_END
  • 具体实现 NSObject+Semaphore.m 内容为:
#import <objc/runtime.h>

inline void SemaphoreAutoLock(NSObject *target, SemaphoreLockBlock block) {
    [target Lock];
    if (block) block();
    [target Unlock];
}

@implementation NSObject (Semaphore)

- (void)Lock {
    dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
}

- (void)Unlock {
    dispatch_semaphore_signal(self.lock);
}

- (dispatch_semaphore_t)lock {
    dispatch_semaphore_t lock = objc_getAssociatedObject(self, @selector(lock));
    if (!lock) {
        lock = dispatch_semaphore_create(1);
        objc_setAssociatedObject(self, @selector(lock), lock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return lock;
}

@end