一、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
}

谢谢您的观看,欢迎关注我的公众号。

image.png


海生
104 声望32 粉丝

与黑夜里,追求那一抹萤火。