【问题标题】:Mutex is not held in this async block互斥锁未保存在此异步块中
【发布时间】:2021-11-02 00:28:30
【问题描述】:

我正在使用 Kotlin 流和 LiveData 代码实验室做高级协程,并在 CacheOnSuccess.kt 中遇到了这个函数。

有一条注释说“// 注意:互斥锁不在此异步块中”。这到底是什么意思?为什么互斥锁不能保存在异步块中?那有什么意义呢?

    suspend fun getOrAwait(): T {
        return supervisorScope {
            // This function is thread-safe _iff_ deferred is @Volatile and all reads and writes
            // hold the mutex.

            // only allow one coroutine to try running block at a time by using a coroutine-base
            // Mutex
            val currentDeferred = mutex.withLock {
                deferred?.let { return@withLock it }

                async {
                    // Note: mutex is not held in this async block
                    block()
                }.also {
                    // Note: mutex is held here
                    deferred = it
                }
            }

            // await the result, with our custom error handling
            currentDeferred.safeAwait()
        }
    }

【问题讨论】:

    标签: mutex android-livedata flow kotlin-coroutines


    【解决方案1】:

    根据withLock 的实现,互斥锁被保存在刚刚的堆栈帧上,这意味着,在withLock 执行之后,互斥锁被释放,但异步中的代码可能不能正确执行帧(根据当前的Dispatchers可能在另一个线程中),所以可能在执行异步块时,withLock调用可能已经返回,至于also调用,它被标记为inline,所以它是在当前帧中执行,就在withLock 返回之前

    【讨论】:

      【解决方案2】:

      互斥锁在任何时候最多由一个协程持有。 async 启动一个不尝试获取互斥锁的协程。其意义与任何其他互斥锁相同——async 块内的代码不受互斥锁保护,因此它不能触及需要由互斥锁保护的状态。

      【讨论】:

        猜你喜欢
        • 2013-01-03
        • 1970-01-01
        • 2011-06-10
        • 2014-05-02
        • 1970-01-01
        • 2018-05-23
        • 1970-01-01
        • 1970-01-01
        • 2021-12-23
        相关资源
        最近更新 更多