Golang 中国
func (bl *BeeLogger) SetLevel(l int) {
    bl.level = l
}

func (bl *BeeLogger) Async() *BeeLogger {
    bl.asynchronous = true
    go bl.startLogger()
    return bl
}

func (bl *BeeLogger) startLogger() {
    for {
        select {
        case bm := <-bl.msg:
            for _, l := range bl.outputs {
                err := l.WriteMsg(bm.msg, bm.level)
                if err != nil {
                    fmt.Println("ERROR, unable to WriteMsg:", err)
                }
            }
        }
    }
}

我看到beego的logs模块里面
bm.level这个属性在两个goroutine中使用到
这种情况不加锁不会出问题么?

以前学C的时候好像说过,一些很简单的赋值语句可能CPU都需要几个指令,如果在中间那个指令CPU时间片切了出去,这时候另一个线程恰好进来读,就会读到内存中前面是新数据后面是旧数据的错误值。这种情况在GO中是不是也会出现?
所以是否只要同一变量在不同goroutine读写都要对变量加锁保证原子性?

2 回复
stevewang
#1 stevewang • 2015-09-14 00:49

需要加锁,或者用atomic方式访问。

undefined
#2 undefined • 2018-08-27 11:29

这种情况没有加锁的必要
首先对整形的存取都是不可分割的原子操作
这段代码极端情况会出现SetLevel修改了level的值,但另外一个并发读取到了旧的level值。这种情况是高并发的小概率事件,且这种极端情况也可以接受,无非是多了(或少了)几条log

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