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
        }
}
                                                       

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM