首页 > 解决方案 > observable.observeOn() 和公共资源的并发问题

问题描述

我在函数中有一个可观察的。该函数发生在某个队列 queueA 中,并且 observable 是通过 observeOn(schedulerB) 订阅的。在 onNext 中,我正在更改一个类变量。

在另一个函数中,我正在从不同的队列中更改同一个类变量。

这是一些代码来演示我的情况:

class SomeClass {

    var commonResource: [String: String] = [:]
    var queueA = DispatchQueue(label: "A")
    var queueB = DispatchQueue(label: "B")
    var schedulerB = ConcurrentDispatchQueueScheduler(queue: QueueB)       

    func writeToResourceInOnNext() {
        let obs: PublishSubject<String> = OtherClass.GetObservable()
        obs.observeOn(schedulerB)
           .subscribe(onNext: { [weak self] res in
            // this happens on queue B
            self.commonResource["key"] = res
        }
    }

    func writeToResource() {
        // this happens on queue A
        commonResource["key"] = "otherValue"
    }
}

我的问题是,如果同时在两个地方修改 commonResource 是否可能存在并发问题?

在使用 observable 的 observable 中写入/读取 onNext 内部的类/全局变量的常见做法是什么?

谢谢大家!

标签: swiftconcurrencyrx-swiftreactivex

解决方案


由于您SomeClass无法控制何时调用这些函数或在哪些线程上回答是肯定的,因此由于其被动性质,您将在此代码中设置并发问题。

这里明显的解决方案是调度到里面writeToResource()的队列 B 以避免竞争条件。

另一种选择是在写入资源之前使用NSLock(或)并锁定它,然后再解锁它。NSRecursiveLock

最佳实践是:当您在订阅函数的闭包内发生副作用时(在这种情况下,写到commonResource闭包是唯一发生副作用的地方。这意味着取消被动writeToResource()函数,而是传入一个由当前调用该函数的任何代码生成的 Observable。


推荐阅读