Golang中国

模块wbw代码:

package wbw

import (
    "fmt"
    "time"
)

var (
    sk      string
    fn      string
    aeskey  string
)
func SrvRun(i int){
    sk = "wbw"
    fn = fmt.Sprintf("全名: %d", time.Now().UnixNano())
    //aeskey = "Aeskey:========================"
    aeskey = fmt.Sprintf("========================%d", time.Now().UnixNano())

    fmt.Printf("i: %d ,sk: %s, fn: %s, aeskey: %s.\n",i,sk, fn, aeskey)
}

func SrvDo(c chan bool, i int){
    SrvRun(i)
    SrvRetRun(i)
    c <- true
}

func SrvRetRun( i int){
    fmt.Printf("i: %d ,sk: %s, fn: %s, aeskey: %s.\n",i,sk, fn, aeskey)
}

主程序代码:

package main

import (
    "fmt"
    "runtime"
    "./wbw"
)

func main(){
    runtime.GOMAXPROCS(runtime.NumCPU())
    fmt.Printf("Run: \n")
    RunProc := 10
    c := make(chan bool, RunProc)
    for i :=0; i< RunProc; i++ {
    go wbw.SrvDo(c, i)
    }
    for i := 0; i < RunProc; i++ {
    <-c
    }
    fmt.Println("DONE.")
}

程序运行结果:

Run: 
i: 2 ,sk: wbw, fn: 全名: 1388118741373181325, aeskey: ========================1388118741373212440.
i: 2 ,sk: wbw, fn: 全名: 1388118741373181325, aeskey: ========================1388118741373212440.
i: 3 ,sk: wbw, fn: 全名: 1388118741373278175, aeskey: ========================1388118741373283101.
i: 3 ,sk: wbw, fn: 全名: 1388118741373278175, aeskey: ========================1388118741373283101.
i: 4 ,sk: wbw, fn: 全名: 1388118741373349461, aeskey: ========================1388118741373355269.
i: 4 ,sk: wbw, fn: 全名: 1388118741373349461, aeskey: ========================1388118741373302891.
i: 5 ,sk: wbw, fn: 全名: 1388118741373382401, aeskey: ========================1388118741373386580.
i: 5 ,sk: wbw, fn: 全名: 1388118741373382401, aeskey: ========================1388118741373386580.
i: 0 ,sk: wbw, fn: 全名: 1388118741373349461, aeskey: ========================1388118741373302891.
i: 6 ,sk: wbw, fn: 全名: 1388118741373410279, aeskey: ========================1388118741373414368.
i: 0 ,sk: wbw, fn: 全名: 1388118741373410279, aeskey: ========================1388118741373414368.
i: 6 ,sk: wbw, fn: 全名: 1388118741373410279, aeskey: ========================1388118741373414368.
i: 1 ,sk: wbw, fn: 全名: 1388118741373432720, aeskey: ========================1388118741373436969.
i: 7 ,sk: wbw, fn: 全名: 1388118741373438829, aeskey: ========================1388118741373442387.
i: 1 ,sk: wbw, fn: 全名: 1388118741373438829, aeskey: ========================1388118741373442387.
i: 7 ,sk: wbw, fn: 全名: 1388118741373438829, aeskey: ========================1388118741373442387.
i: 8 ,sk: wbw, fn: 全名: 1388118741373461325, aeskey: ========================1388118741373465624.
i: 8 ,sk: wbw, fn: 全名: 1388118741373470581, aeskey: ========================1388118741373474104.
i: 9 ,sk: wbw, fn: 全名: 1388118741373470581, aeskey: ========================1388118741373474104.
i: 9 ,sk: wbw, fn: 全名: 1388118741373470581, aeskey: ========================1388118741373474104.
DONE.

模块wbw的两个函数: SrvRun, SrvRetRun 他们的输出应该是一致的才对,可是从输出来看 i: 4这两行的内容并不一致,输出的不一致是由于变量 fn或者aeskey被修改了。

如果我将主程序中语句runtime.GOMAXPROCS(runtime.NumCPU()) 注释后得到的结果始终都是正确的, 请问我如果要启用GOMAXPROCS特性,应该如何才能确保我模块 SrvRun, SrvRetRun两个的函数输出是一致的,而且我发现如果开启GOMAXPROCS特性,不同GO程中的相同的变量名会发生改变。

请问我应该如何处理该问题。谢谢!


wzhuzhu 于 2013-12-27 12:58 修改
6 回复
wzhuzhu
#1 wzhuzhu • 2013-12-27 14:20

是否是mainimport wbw模块的时候,在 go wbw.SrvDo(c, i) 使用的是继承自main中导入的wbw模块的变量,导致了不同的GO程都访问了同一个变量,才会出现上面运行程序的这种情况?

manzhiyong
#2 manzhiyong • 2013-12-27 15:00

通道设置了缓存,就编程非阻塞的了,除非缓存满了,所以变量被其他通道给重置了.

manzhiyong
#3 manzhiyong • 2013-12-27 17:07

管道没有缓存好像也不行,因为阻塞前变量就被重置了,可行的方法有几种: 1,把变量设置为数组或切片,通过下表i来赋值. 2,变量通过参数传入,而不是在该包内设置为全局的. 3,在go后立即调用<-c,不过这样就不是多进程了

wzhuzhu
#4 wzhuzhu • 2013-12-27 22:47

多谢,包内不使用全局的变量应该简单一点。

lwmonster
#5 lwmonster • 2016-04-08 18:46

多线程访问了共享的全局变量,访问前应该加锁…

bigbear
#6 bigbear • 2016-04-11 13:31

楼上正解, 并发访问, 应该加锁

需要 登录 后方可回复, 如果你还没有账号你可以 注册 一个帐号。