Parallel processing goroutines在多核处理器上的行为如何

Parallel processing goroutines在多核处理器上的行为如何,parallel-processing,go,goroutine,Parallel Processing,Go,Goroutine,我是围棋语言的新手,如果我的问题很基本,请原谅。我编写了一个非常简单的代码: func main(){ var count int // Default 0 cptr := &count go incr(cptr) time.Sleep(100) fmt.Println(*cptr) } // Increments the value of count through pointer var func incr(cptr *int) {

我是围棋语言的新手,如果我的问题很基本,请原谅。我编写了一个非常简单的代码:

func main(){
    var count int // Default 0

    cptr := &count

    go incr(cptr)

    time.Sleep(100)

    fmt.Println(*cptr)
}

// Increments the value of count through pointer var
func incr(cptr *int) {
    for i := 0; i < 1000; i++ {
            go func() {
                    fmt.Println(*cptr)
                    *cptr = *cptr + 1
            }()
      }
    }
func main(){
var count int//默认值为0
cptr:=&计数
执行增量(cptr)
时间。睡眠(100)
fmt.Println(*cptr)
}
//通过指针变量递增count的值
函数增量(cptr*int){
对于i:=0;i<1000;i++{
go func(){
fmt.Println(*cptr)
*cptr=*cptr+1
}()
}
}
count的值应增加循环运行次数的一倍。考虑以下情况:

循环运行100次-->计数的值为100(这与循环运行100次是正确的)

循环运行次数>510次-->计数值为508或510。即使是100000,也会发生这种情况


我在一台8核处理器的机器上运行此程序。

您的代码非常快速:您可以从不同的、未同步的goroutine写入相同的内存位置,而无需任何锁定。结果基本上没有定义。您必须a)确保所有goroutine写入都以一种良好、有序的方式进行,或者b)通过例如互斥来保护每次写入,或者c)使用原子操作


如果您编写这样的代码:请始终在比赛检测器下尝试,如
$go run-race main.go
并修复所有比赛

首先:在Go 1.5之前,它在单个处理器上运行,只使用多个线程来阻止系统调用。除非您告诉运行时使用更多处理器

从Go 1.5开始,GOMAXPROCS设置为CPU数量。见

此外,操作
*cptr=*cptr+1
不保证是原子的。若你们仔细观察,它可以分为3个操作:通过解引用指针获取旧值,增加值,将值保存到指针地址

您得到508/510的事实是由于运行时中的一些魔力,而不是定义为保持这种状态。有关并发操作行为的更多信息,请参阅。

您可能得到了的正确值在这种情况下,使用通道的一个很好的替代方法可能是软件包,它专门包含用于原子递增/递减数字的函数。

所有这些方法都失败了,
这里没有。但我找到了更好的方法

我正在使用sync包来解决这个问题,并等待所有goroutine完成,而不需要睡眠或频道


别忘了看看那篇很棒的帖子,你正在生成500或1000个例程,而这些例程之间没有同步。这将创建一个竞争条件,从而使结果不可预测

假设你在办公室工作,为你的老板计算费用余额

你的老板与1000名下属开会,他在会上说:“我会给你们所有人发奖金,所以我们必须增加开支记录。”。他发布了以下命令: i) 去找Nerve,问问他/她当前的费用余额是多少 ii)打电话给我的秘书,询问您将获得多少奖金 iii)将奖金作为费用添加到额外费用余额中。你自己算吧。 iv)要求Nerve在我的授权下填写新的费用余额

所有1000名热切的参与者都争先恐后地记录他们的奖金,并创造了一个比赛条件

他们问,如果50只渴望的地鼠同时(几乎)击中了神经, i) “当前费用余额是多少? --Nerve说给所有50只地鼠1000美元,因为他们在余额为1000美元的同一时间(几乎)问了同一个问题。 ii)然后地鼠打电话给秘书,应该给我多少奖金? 秘书回答:“公平地说,只要1美元。” iii)Boos说,算算一下,他们都计算出1000美元+1美元=1001美元应该是公司的新成本余额 iv)他们都会要求Nerve将1001美元放回余额

你看到渴望地鼠的方法中的问题了吗? 有50美元的计算单位,每增加1美元到现有的余额,但成本没有增加50美元,只增加了1美元


希望这能澄清问题。现在对于解决方案,其他贡献者给出了非常好的解决方案,我相信这就足够了。

有什么原因它依赖于输入吗?对于小于510的值,它总是打印正确的o/p。没有原因,只是偶然。正如沃尔克所说,对于小值它正确的原因基本上只是随机的调度程序导致预期行为的原因。它在大于510的情况下失败的原因可能是因为您睡眠了100 ns,然后退出,因此508/510值正好是主程序唤醒并退出时的值。这将随系统负载和其他因素而随机变化。内存模型链接实际上非常好d清除了很多东西。a)仅链接的答案不适合。b)对于一个简单的计数器来说,使用这种方式是过分的;如果它只是一个计数器
sync。原子的
是非常优越的。嘿,谢谢你的提示,你能重写一个更好的方法吗?