背景
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