golang atomic.Value实践以及原理

本文探讨了在Golang中如何使用atomic.Value进行并发安全的接口类型数据存储与加载,详细解析了其数据结构、Store和Load的操作流程,并强调了使用atomic.Value时的注意事项与效率优势。
摘要由CSDN通过智能技术生成

golang atomic.Value实践以及原理

最近一个项目中某个对象需要持有一个统计对象,并且需要能够原子的更新这个统计对象(并发读写场景下),避免data race。为了避免对象的copy, 肯定是要持有这个统计对象的指针了。 此外,这个统计对象其实是统计的模型,需要能够随时替换成其余的统计实现。所以很自然的选用了 interface{}来保存。

type Obj struct {
   
	data interface{
   }
}

但是有个问题,golang 里面的atomic没有提供方法来实现interface{}的原子读写。但是atomic提供了 atomic.Value. 该类型可以原子更新 interface{}。

数据结构

先看数据结构的定义:

// A Value provides an atomic load and store of a consistently typed value.
// The zero value for a Value returns nil from Load.
// Once Store has been called, a Value must not be copied.
// A Value must not be copied after first use.
type Value struct {
   
	v interface{
   }
}

// ifaceWords is interface{} internal representation.
type ifaceWords struct {
   
	typ  unsafe.Pointer
	data unsafe.Pointer
}

atomic.Value 里面其实维护的就是一个 interface{}. 然后提供原子的更新这个interface{}的方法。

注意注释所说的,提供的是原子的Store 和 load 一个类型一致的value。也就是说 atomic.Value 一旦第一次Store了一个value, 那么后面的Store就必须是同一个类型的value。然后就是在store之后,Value不能被复制。

注意到下面还有一个结构:ifaceWords ,这个其实是对 interface{} 内部结构的表示。我们知道一个interface{}会被编译编译成 eface 结构或则 iface 结构。定义在 runtime/runtime2.go 里面。eface表示一个空接口,iface描述的是非空接口,它包含方法。

type iface struct {
   
	tab  *itab
	data unsafe.Pointer
}

type eface struct {
   
	_type *_type
	data  unsafe.Pointer
}

不管是 iface 还是 eface 里面保存的都是两个指针对象。所以我们可以把 interface{} 对象的指针转换成*ifaceWords,这与后面的Store 和 Load息息相关。

关于非类型安全的指针转换unsafe.Pointer,可以参考这篇文章:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值