go 語言 atomic-Value 源碼閱讀

一、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
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/bYidITLeSAwvbhEYF2zUZw