一、atomic.Value介绍
atomic.Value被设计用来存储任意类型的数据,所以它内部的字段是一个interface{}类型。
源码在 src/sync/atomic/value.go 中
type Value struct {
v interface{}
}
除了atomic.Value外,atomic包内部定义了一个ifaceWords类型,这其实是interface{}的内部表示 (runtime.eface),它的作用是将interface{}类型分解,得到其原始类型(typ)和真正的值(data)。
// ifaceWords is interface{} internal representation.
type ifaceWords struct {
typ unsafe.Pointer
data unsafe.Pointer
}
把 atomic.Value转换成ifaceWords使用强制类型转化如下
v := atomic.Value{}
vp := (*atomic.ifaceWords)(unsafe.Pointer(v))
这样我们就可以得到 atomic.Value 对应的 ifaceWords格式
然后获取对应的typ以及data两个字段属性
二、atomic.Value的使用
我们使用go doc atomic.Value的到 atomic.Value的主要使用方法有 Load以及store,查询和存储两个方法。
func (v *Value) Load() (x interface{})
func (v *Value) Store(x interface{})
2.1、Store()存储介绍
三、atomic.Value代码演进
3.1、实现一个基于共享内存的Store和Load
package v1
type Value struct {
v interface{}
}
func (v *Value) Store(x interface{}) {
v.v = x
}
func (v *Value) Load() (x interface{}) {
return v.v
}
代码实现了简单的基于共享内存的 sotre和load
我们写一个store和load的用例
func TestStore(t *testing.T) {
v := Value{v: "hello"}
t.Log(v.Load()) //hello
v.Store("world")
t.Log(v.Load()) //world
}
问题:这个在高并发,多协程的情况下,没法保证并发安全,数据的一致性?
解决方案1:加锁
解决方案2:原子化操作
3.2、并发安全-加锁共享内存读写
package v2
import "sync"
type Value struct {
sync.RWMutex
v interface{}
}
func (v *Value) Store(x interface{}) {
v.Lock()
v.v = x
v.Unlock()
}
func (v *Value) Load() (x interface{}) {
v.Lock()
defer v.Unlock()
return v.v
}
在高并发情况下,不停的加锁,解锁,也是一种开销,我们可以试试更轻量级的原子化直接操作内存。
3.3并发安全-原子化共享内存读写
package atomic
import "unsafe"
type Value struct {
v interface{}
}
type ifaceWords struct {
typ unsafe.Pointer
data unsafe.Pointer
}
func (v *Value) Store(x interface{}) {
vp := (*ifaceWords)(unsafe.Pointer(v))
xp := (*ifaceWords)(unsafe.Pointer(&x))
vp.typ = xp.typ
vp.data = xp.data
}
func (v *Value) Load() (x interface{}) {
vp := (*ifaceWords)(unsafe.Pointer(v))
xp := (*ifaceWords)(unsafe.Pointer(&x))
xp.typ = vp.typ
xp.data = vp.data
return x
}
代码实现了简单的基于共享内存的 sotre和load
我们写一个store和load的用例
func TestStore(t *testing.T) {
v := Value{v: "hello"}
t.Log(v.Load()) //hello
v.Store("world")
t.Log(v.Load()) //world
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。