问题:任务A,B,C先执行A和B再执行C可以怎么实现(group,条件锁,barrier)

方案1、group 通过创建信号量访问资源数量为1,然后通过wait和sign顺序执行group内线程。

方案2、NSConditionLock,通过控制创建条件和解锁条件,顺序执行线程。

let lock = NSConditionLock.init(condition: 3)

DispatchQueue.global().async {
    lock.lock(whenCondition: 3)
    print("A")
    lock.unlock(withCondition: 2)
}

DispatchQueue.global().async {
    lock.lock(whenCondition: 2)
    print("B")
    lock.unlock(withCondition: 1)
}

DispatchQueue.global().async {
    lock.lock(whenCondition: 1)
    print("C")
    lock.unlock()
}

方案3、barrier 允许在一个并发队列中创建一个同步点。当在并发队列中遇到一个barrier, 他会延迟执行barrier的block,等待所有在barrier之前提交的blocks执行结束。 这时,barrier block自己开始执行。

二、条件锁

1、条件锁定义

@interface NSConditionLock : NSObject <NSLocking> {
@private
    void *_priv;
}
//初始化一个NSConditionLock对象
- (instancetype)initWithCondition:(NSInteger)condition NS_DESIGNATED_INITIALIZER;

@property (readonly) NSInteger condition;  //锁的条件

//满足条件时加锁
- (void)lockWhenCondition:(NSInteger)condition;


- (BOOL)tryLock;
//如果接收对象的condition与给定的condition相等,则尝试获取锁,不阻塞线程
- (BOOL)tryLockWhenCondition:(NSInteger)condition;

//解锁后,重置锁的条件
- (void)unlockWithCondition:(NSInteger)condition;

- (BOOL)lockBeforeDate:(NSDate *)limit;

//在指定时间前尝试获取锁,若成功则返回YES 否则返回NO
- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;

@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

@end

条件锁使用代码示例:

//主线程中
NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:0];

//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [lock lockWhenCondition:1];
    NSLog(@"线程1");
    sleep(2);
    [lock unlock];
});

//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);//以保证让线程2的代码后执行
    if ([lock tryLockWhenCondition:0]) {
        NSLog(@"线程2");
        [lock unlockWithCondition:2];
        NSLog(@"线程2解锁成功");
    }
    else {
        NSLog(@"线程2尝试加锁失败");
    }
});

//线程3
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // sleep(2);//以保证让线程2的代码后执行
    if ([lock tryLockWhenCondition:2]) {
        NSLog(@"线程3");
        [lock unlock];
        NSLog(@"线程3解锁成功");
    }
    else {
        NSLog(@"线程3尝试加锁失败");
    }
});

//线程4
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // sleep(3);//以保证让线程2的代码后执行
    
    [lock lockWhenCondition:2];
    NSLog(@"线程4");
    [lock unlockWithCondition:1];
    NSLog(@"线程4解锁成功");
    
});

打印结果

2018-04-17 16:59:26.995255+0800 NSLock测试[48379:5945905] 线程3尝试加锁失败
2018-04-17 16:59:28.000120+0800 NSLock测试[48379:5945903] 线程2
2018-04-17 16:59:28.000791+0800 NSLock测试[48379:5945903] 线程2解锁成功
2018-04-17 16:59:28.000851+0800 NSLock测试[48379:5945904] 线程4
2018-04-17 16:59:28.001999+0800 NSLock测试[48379:5945904] 线程4解锁成功
2018-04-17 16:59:28.002044+0800 NSLock测试[48379:5945902] 线程1

结果说明:

1、初始化一个条件锁,条件为0
2、由于线程1 和线程4条件不满足,所以循环一段时间休眠,等待满足条件满足时唤醒;线程3尝试加锁,不会阻塞线程,但是条件不满足所以直接休眠;线程2休眠1秒后尝试加锁。满足条件所以加锁成功;
3、 线程2伴随重置加锁条件2进行解锁;
4、 此时线程4满足条件,系统唤醒进行加锁,并且重置加锁条件14
5、 此时线程1满足条件,系统唤醒进行加锁,并且解锁,此时条件为1

转载地址:
iOS锁系列-NSConditionLock条件锁

iOS 面试题集