首页  >  文章  >  后端开发  >  为什么我的 Goroutine 递增变量会产生意外结果?

为什么我的 Goroutine 递增变量会产生意外结果?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-10-29 20:38:29625浏览

Why Does My Goroutine Incrementing a Variable Produce Unexpected Results?

这是编译器优化的结果吗?

在此代码片段中,启动了一个 goroutine 并重复递增变量 i:

<code class="go">package main

import "time"

func main() {
    i := 1
    go func() {
        for {
            i++
        }
    }()
    <-time.After(1 * time.Second)
    println(i)
}</code>

但是,输出始终为 1。这种行为可以归因于 Go 内存模型和此代码的具体实现。

Go 内存模型

Go 内存模型定义了条件在这种情况下,可以保证在一个 goroutine 中读取变量时观察到在不同 goroutine 中写入同一变量所产生的值。它强调了同步对于并发访问共享数据的重要性。

省略同步

在给定的代码中:

  • 对 i 的赋值(即 i )后面没有任何同步事件,表明更改可能不会立即对其他 goroutine 可见。
  • 编译器可以通过将其简化为无操作来优化此循环优化。

编译器优化

激进的编译器可能会删除 i 语句,有效地将 goroutine 缩减为:

<code class="go">for {}</code>

同步示例

为了证明问题源于由于缺乏同步,请考虑以下代码:

<code class="go">package main

import (
    "sync"
    "time"
)

func main() {
    mx := new(sync.Mutex)
    i := 1
    go func() {
        for {
            mx.Lock()
            i++
            mx.Unlock()
        }
    }()
    <-time.After(1 * time.Second)
    mx.Lock()
    println(i)
    mx.Unlock()
}</code>

在这种情况下,输出不再是 1,而是一个很大的数字,正如预期的那样。 sync.Mutex 提供同步并确保两个 goroutine 以受控方式访问 i,允许 goroutine 递增 i 并使更改对主例程可见。

以上是为什么我的 Goroutine 递增变量会产生意外结果?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn