NSConditionLock
NSConditionLock.h
@interface NSConditionLock : NSObject <NSLocking> {
@private
void *_priv;
}
- (instancetype)initWithCondition:(NSInteger)condition NS_DESIGNATED_INITIALIZER;
@property (readonly) NSInteger condition;
- (void)lockWhenCondition:(NSInteger)condition;
- (BOOL)tryLock;
- (BOOL)tryLockWhenCondition:(NSInteger)condition;
- (void)unlockWithCondition:(NSInteger)condition;
- (BOOL)lockBeforeDate:(NSDate *)limit;
- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;
@property (nullable, copy) NSString *name NS_AVAILABLE(10_5, 2_0);
@end
NSConditionLock的使用
- (void)viewDidLoad {
[super viewDidLoad];
//主线程中
TestObj *obj = [[TestObj alloc] init];
NSConditionLock *lock = [[NSConditionLock alloc] init];
//线程1
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (NSUInteger i=0; i<3; i++) {
[lock lock];
NSLog(@"循环中,i的值为:%lu", (unsigned long)i);
[obj method1];
sleep(1); //线程1执行挂起2秒
[lock unlockWithCondition:i];
}
});
//线程2
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1); //线程2执行挂起1秒,以保证一定是线程1先执行
//需要标识为2的钥匙才能进行加锁操作,这里等待线程1对lock的循环操作达到它需要的加锁条件;如果最终不符合条件(例如:线程1的条件判断是i<4时),将阻塞线程内容向下执行;这里就得用tryLockWhenCondition:方法控制
BOOL isLocked = [lock tryLockWhenCondition:2];
[obj method2];
if (isLocked) { //加锁解锁必须成对操作,否则会报错
[lock unlock];
}
});
}
2016-11-06 15:47:10.028 SSS[20142:868873] 循环中,i的值为:0
2016-11-06 15:47:10.028 SSS[20142:868873] method1
2016-11-06 15:47:11.103 SSS[20142:868873] 循环中,i的值为:1
2016-11-06 15:47:11.104 SSS[20142:868873] method1
2016-11-06 15:47:12.177 SSS[20142:868873] 循环中,i的值为:2
2016-11-06 15:47:12.177 SSS[20142:868873] method1
2016-11-06 15:47:14.320 SSS[20142:868873] method2
在线程1中的加锁使用了 lock,所以是不需要条件的,所以顺利的就锁住了,但在 unlock 的使用了一个整型的条件,它可以开启其他线程中正在等待这把钥匙的临界地,而线程2则需要一把被标识为2的钥匙,所以当线程1循环到最后一次的时候,才最终打开了线程2中的阻塞。但即便如此,NSConditionLock 也跟其他的锁一样,是需要 lock 与 unlock 对应的,只是 lock,lockWhenCondition: 与 unlock,unlockWithCondition: 是可以随意组合的,当然这是与你的需求相关的。