【问题标题】:Golang Goroutines - Fix Race Condition using Atomic FunctionsGolang Goroutines - 使用原子函数修复竞争条件
【发布时间】:2021-09-23 04:01:01
【问题描述】:

我是 Golang 的新手,我正在尝试理解 goroutines。 这是我从https://www.golangprograms.com/goroutines.html 得到的一段代码。

package main

import (
    "fmt"
    "runtime"
    "sync"
    "sync/atomic"
)

var (
    counter int32          // counter is a variable incremented by all goroutines.
    wg      sync.WaitGroup // wg is used to wait for the program to finish.
)

func main() {
    wg.Add(3) // Add a count of two, one for each goroutine.

    go increment("Python")
    go increment("Java")
    go increment("Golang")

    wg.Wait() // Wait for the goroutines to finish.
    fmt.Println("Counter:", counter)

}

func increment(name string) {
    defer wg.Done() // Schedule the call to Done to tell main we are done.

    for range name {
        fmt.Println("name:", name)
        fmt.Println("Counter in range:", counter)
        atomic.AddInt32(&counter, 1)
        runtime.Gosched() // Yield the thread and be placed back in queue.
    }
}

输出:

name: Golang
Counter in range: 0
name: Java
Counter in range: 1
name: Golang
Counter in range: 2
name: Golang
Counter in range: 3
name: Java
Counter in range: 4
name: Golang
Counter in range: 5
name: Python
Counter in range: 6
name: Java
Counter in range: 7
name: Golang
Counter in range: 8
name: Java
Counter in range: 9
name: Golang
Counter in range: 10
name: Python
Counter in range: 11
name: Python
Counter in range: 12
name: Python
Counter in range: 13
name: Python
Counter in range: 14
name: Python
Counter in range: 15
Counter: 16

我无法理解为什么输出是 16。即使我们只添加了 3 个 goroutine。不应该是3吗?

谁能解释一下?

谢谢。

【问题讨论】:

    标签: go atomic race-condition goroutine


    【解决方案1】:

    我无法理解为什么输出是 16。即使我们只添加了 3 个 goroutine。不应该是3吗?

    为什么应该是 3?它应该被调用多次atomic.AddInt32(&counter, 1)

    那是多少次?你启动了 3 个 goroutine,每个 goroutine 都有一个循环。递增是在循环内完成的。

    循环:

    for range name {}
    

    string 上的 for range 迭代 string 的符文。您的案例中的名称是GolangJavaPython。因此,循环体的执行次数与这些字符串所具有的符文数一样多:Golang 为 6 个,Java 为 4 个,Python 为 6 个,加起来为 16。

    【讨论】:

    • 我忽略了range 函数。非常感谢您的解释。我现在很清楚了。
    • 你能给我一些有用的链接或教程来学习 Golang 吗?我昨天刚开始使用 Golang,并在一些好东西上苦苦挣扎。
    • 官方主页及其链接是一个不错的起点:golang.org
    【解决方案2】:

    您是给定输入字符串的范围,trange 将其视为一个数组并对其进行迭代。 看这个例子

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        increment("test")
        increment("test_dev")
        increment("test_deploy")
        
    }
    
    func increment(name string) {
        for i, value := range name {
            fmt.Printf("name: %s index: %d, char: %c\n", name, i, value)
    
        }
    }
    

    【讨论】:

    • 感谢您的回复。我知道范围是如何工作的。我只是错过了示例中的范围功能。
    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多