zoukankan      html  css  js  c++  java
  • goroutine 修改全局变量无效问题

    原文:https://studygolang.com/topics/7050

    go修改全局变量的问题

    测试 goroutine 修改全局变量,有x y 两个全局函数,分别在两个 goroutine f1() 和 f2() 中修改(f1()修改x,f2()修改y),f2() 只多了一行sleep,为什么最终主 goroutine 打印y时,y的值一直是0?? 代码如下

    package main
    
    import (
        "fmt"
        "runtime"
        "time"
    )
    
    var x, y int
    
    func main() {
        runtime.GOMAXPROCS(3)
        go f1()
        go f2()
        for {
            time.Sleep(time.Second * 1)
            fmt.Println("x:", x, "y", y)
        }
    }
    
    func f1() {
        for {
            x = x + 1
            time.Sleep(time.Second * 1)
        }
    }
    
    func f2() {
        for {
            y = y + 1
        }
    }
    

      

    结果:

    我的理解是这样的,不知道是否合理。 为了效率,对内存的写入一般会在每一个处理器中缓冲,并在必要时一起flush到主存。而f2没有Sleep,导致一直没有时间片去flush到主存,f1有Sleep,就会flush到主存,所以x值会变化,y的值没变化。

    如果runtime.GOMAXPROCS(1),都不会有打印信息出来。被f2独占

    可以这样修改,就会变化

    package main
    
    import (
        "fmt"
        "runtime"
        "time"
    )
    
    var x, y int
    
    func main() {
        fmt.Println(runtime.NumCPU())
        runtime.GOMAXPROCS(3)
        go f1(&x)
        go f2(&y)
        for {
            time.Sleep(time.Second * 1)
            fmt.Println("x:", x, "y", y)
        }
    }
    
    func f1(x *int) {
            for {
                    *x = *x + 1
                    time.Sleep(time.Second * 1)
            }
    }
    
    func f2(y *int) {
            for {
                    *y = *y + 1
            }
    }
    
    smokezl
    smokezl · #2 · 7月之前

    1楼 @darren3126 对的,我觉得应该是这样,f1 和 f2 如果都不sleep 的话,相当于分别都独占了M,没有机会写主存 </br>我也测试过,如果是传址的话,值确实会被修改,感谢大神~

    TOMFATCAT
    TOMFATCAT · #3 · 7月之前

    这完全是为了安全,如果你想改变全局变量,可以把它塞到chan里面,要在通信里共享内存,大概是这么理解的,不然所有协程一块去写同一块内存,不加锁还,很容易写花的

    package main
    
    import (
        "fmt"
        "runtime"
        "time"
    )
    
    var x, y int
    
    func main() {
        fmt.Println(runtime.NumCPU())
        runtime.GOMAXPROCS(3)
        x = 100
        y = 33
        go f1(&x)
        go f2(&y)
        for {
            time.Sleep(time.Second * 1)
            fmt.Println("x:", x, "y", y)
        }
    }
    
    func f1(x *int) {
            for {
                    *x = *x + 1
                    time.Sleep(time.Second * 1)
            }
    }
    
    func f2(y *int) {
            for {
                    *y = *y + 1
            }
    }
                                                           
    

      

  • 相关阅读:
    Windows Phone 的控件倾斜效果
    在framework4.0 3.5中反序列化 解析JSON
    PhpStorm2.0、3.0,5.0注册码到2112年
    Windows Phone(wp7)系统长按的秘密
    配置ethereal编译环境
    复习C++:引用的一些用法
    转载
    Stay hungry,Stay foolish
    C++:继承的一点注意事项
    纯虚函数
  • 原文地址:https://www.cnblogs.com/oxspirt/p/11037887.html
Copyright © 2011-2022 走看看