golang的atomic库之隐患以及我做的改进

atomic库并不能杜绝race冲突

与sync.Map不同,atomic库并不杜绝传统的方式去访问变量。

这样,即使你在所有的写操作中都严格使用atomic.Store类函数,当你用普通方式访问该全局变量时,如=操作,或者在条件语句中的逻辑判断(“==”,"!="之类),依然非互斥的读取了,依然可能与正在写的操作发生冲突。

检查方法
go build -race [其它参数]
编译好的程序一运行就发现了WARNING: DATA RACE

你可以说,这只是个警告而已。但是在实际运行中,万一这读写操作同时发生了,就会立即崩溃(panic)。

我的改进

简单粗暴的把数据扩充成带锁的,读写都必须通过特殊用法(函数)

package main

import (
    "fmt"
    "sync"
    )

\\\\以下这段可以单做成一个global package
type Int struct{
    mutex   sync.Mutex
    value   int
}

func (I *Int) Save(n int){
    I.mutex.Lock()
    I.value = n
    I.mutex.Unlock()
}

func (I *Int) Load() int{
    I.mutex.Lock()
    defer I.mutex.Unlock()
    return I.value
}
\\\\\\\\\\\\\\\

var S = &Int{}

func main() {   
   S.Save(5)
   fmt.Printf("S=%v, S.value=%d \n", S,  S.value)
   fmt.Println("S:", S.Load())
}

现在所有的全局变量都照此办理,只不过针对不同类型,需要补充struct外包类型,以及相应的用法函数。

而且一旦这些定义单放在一个库,如起名global中,即使S想改写或读取,都不可能直接调用S.value, 因为Int类型是在另一个库,且里面的内容value是小写,私有的禁止跨库调用,则调用只能通过Save或Load这些用法了。

也就是只要用了此种方法,工程中任何场合的该变量必须照此办理,就杜绝了隐患。

最新版的go1.18已经采用

经过我发文来挑战现有问题
A patch to avoid point-time race coincidence like Rust

最新的atomic库已经实现了类似功能
Improving safe global variables with generic or inheritance

只要你的go版本能顺利编译并运行如下代码,输出0,就是有此功能的:

package main

import (
	"fmt"
	"sync/atomic"
)

var a = atomic.Int32{}

func main() {
	fmt.Println(a.Load())
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值