NSConditionLock解决回调顺序场景

NSConditionLock条件锁在开发中几乎很少用到,虽然知道他的作用但是之前并没有碰到一个用它解决问题的场景。
描述如下一个场景:三个异步任务在并发队列中,同时执行一个耗时任务X,当X执行完毕之后会回调一次数据,如何保证调用顺序和回调顺序一致?
eg:ABC三个异步任务依次书写,并发异步下假如实际调用顺序为BCA,希望回调顺序也是BCA,但其实可能A执行X时最先处理完,但不回调,等待BC回调过后再进行回调,即调用顺序为BCA,回调顺序为BCA,且并发。

利用NSConditionLock可以比较方便实现这个效果,思路如下:通过一个容器记录方法的调用顺序,主动解锁第一个调用,第一个调用一次解锁剩下的调用。

前置一个问题,如果我先进行条件解锁,再进行同条件加锁,此处无效,像下面这样

self.conditionLock.unlock(withCondition: 4)
self.conditionLock.lock(whenCondition: 4)
print("aaa")

正文:
变量部分:

var methodIndex : Array = Array()  //标记调用顺序的容器
    var methodIndexLock : NSLock = NSLock.init() //给容器读写加锁的互斥锁
    var methodCurrnetLock : Int = 0 //当前解锁到的位置
    
    lazy var conditionLock : NSConditionLock = {
        return NSConditionLock.init(condition: 0)
    }() //条件锁
//并发调用三个异步任务,为了比较直观,我把第一个任务进行延迟
    func testConditionLock() {
        DispatchQueue.global().asyncAfter(deadline: .now() + 0.5, execute: {
            print("第一个任务开始了")
            self.someMethod(1) {
                print("第一个任务返回了")
            }
        })
        DispatchQueue.global().async {
            print("第二个任务开始了")
            self.someMethod(2) {
                print("第二个任务返回了")
            }
        }
        DispatchQueue.global().async {
            print("第三个任务开始了")
            self.someMethod(3) {
                print("第三个任务返回了")
            }
        }
        
        //这里备注下:此处是希望解锁第一个加锁的,也就是像上面前置问题那样,使第一把条件锁无效
        DispatchQueue.main.asyncAfter(deadline: .now()+1) {
            self.conditionLock.unlock(withCondition: self.methodIndex[0])
        }
    }
//第一个参数只是一个标识,不代表调用顺序
func someMethod(_ actionIndex:Int,callback:()->Void) {
        //对容器读写加锁
        self.methodIndexLock.lock()
        self.methodIndex.append(actionIndex)
        self.methodIndexLock.unlock()
        
        let t = Double(arc4random() % 10)
        Thread.sleep(forTimeInterval: t) //此处进行休眠,模拟耗时操作
        print(actionIndex,t)
        self.conditionLock.lock(whenCondition: actionIndex)
        callback()
        self.methodCurrnetLock += 1
        guard self.methodIndex.count > self.methodCurrnetLock else {
            return
        }
        self.conditionLock.unlock(withCondition: self.methodIndex[self.methodCurrnetLock])
        print(self.methodCurrnetLock,self.methodIndex)
        
    }

你可能感兴趣的:(NSConditionLock解决回调顺序场景)