如何在Coroutines中实现原子更新

发布于 2025-01-22 06:52:48 字数 681 浏览 2 评论 0原文

这是Coroutines stateflow的更新功能。我有两个问题:

  1. 原子如何?我们内部有多次操作,如何在不相互排斥的情况下保证原子能?
  2. 为什么在(true)循环中?在什么条件下,循环是必要的?
  3. 循环可以无尽吗?
/**
 * Updates the [MutableStateFlow.value] atomically using the specified [function] of its value.
 *
 * [function] may be evaluated multiple times, if [value] is being concurrently updated.
 */
public inline fun <T> MutableStateFlow<T>.update(function: (T) -> T) {
    while (true) {
        val prevValue = value
        val nextValue = function(prevValue)
        if (compareAndSet(prevValue, nextValue)) {
            return
        }
    }
}

Here's update function from Coroutines StateFlow. I have two questions:

  1. How is it atomic? We have multiple operations inside, how can atomicity be guaranteed without mutual exclusion?
  2. Why is it in while(true) loop? At what condition the loop is necessary?
  3. Can the loop be endless?
/**
 * Updates the [MutableStateFlow.value] atomically using the specified [function] of its value.
 *
 * [function] may be evaluated multiple times, if [value] is being concurrently updated.
 */
public inline fun <T> MutableStateFlow<T>.update(function: (T) -> T) {
    while (true) {
        val prevValue = value
        val nextValue = function(prevValue)
        if (compareAndSet(prevValue, nextValue)) {
            return
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你另情深 2025-01-29 06:52:48
  1. 更新操作本身不是原子,其中有多个操作。但是,它实际交换了新状态的过时状态的部分:compareAndset(prevvalue,nextValue)是原子。
  2. 这是巧妙的部分:它使用CAS(比较和集合)技术 - 与我正在谈论的方法调用不同 - 我们将旧值复制到prevvalue,然后新值应通过在prevvalue上运行lambda,函数。这为我们提供了nextValue。现在,我们需要记住,我们必须运行线程安全代码,因此prevvalue在运行该函数时可能会更改,因此,compareandset(prevvalue,nextValue)< /code>执行以下内容(从Kotlin引用):“从原子上将当前值与期望进行比较,并将其设置为如果等于期望。因此,这意味着如果prevvalue与当前值不满(这意味着另一个线程在运行函数时已更新了当前值),那么我们应该再次重复整个循环,否则我们返回。此方法保证了线程安全性,我们将永远不会覆盖另一个线程的更改,反之亦然!
  3. 是的,就像中的所有循环一样,(true)在有条件的休息中,此循环将无限期地运行,直到concormeandset返回true。撇开这几天,我前几天学到了一些东西:kotlin coroutines继承 iSACTIVE ,您可以使用它来创建一个合规的coroutine,当执行while(isacative)时,可以取消示波器时取消/代码>。很少是,而(true)是一个好主意:)
  1. The update operation itself isn't atomic, there are multiple operations within it. However, the part where it actually swaps out the out-of-date state for the new state: compareAndSet(prevValue, nextValue) is atomic.
  2. This is the clever part: it uses CAS (Compare And Set) technique - different to the method call I was talking about - whereby we copy the old value into prevValue and then what the new value should be by running the lambda, function on prevValue. This gives us the nextValue. Now, we need to remember that we must be running thread-safe code, so the prevValue might have changed while we were running the function, for this reason, compareAndSet(prevValue, nextValue) does the following (from the Kotlin reference): "Atomically compares the current value with expect and sets it to update if it is equal to expect. The result is true if the value was set to update and false otherwise.". So, what this means is that if prevValue is out of date with the current value (this means that another thread has updated the current value while we were running the function) then we should repeat the whole loop again, otherwise we return. This method guarantees thread safety, we will never overwrite changes from another thread and vice versa!
  3. Yes, as with all loops in a while(true) with a conditioned break, this loop will run indefinitely, until compareAndSet returns true. Just as an aside to this, something I learned the other day: Kotlin coroutines inherit isActive, you can use this to create a compliant coroutine that can cancel when the scope is shut down by doing while(isActive). Rarely is while(true) a good idea :)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文