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