原子操作
Go语言运行时调度系统会恰当安排所有goroutine的运行,在同一时刻,只可能有少数goroutine处于运行状态,并且这个数量只会与M的数量一致,而不会睡着G的增多而增多
_
为了公平起见,Golang调度器会频繁的换上或换下这些goroutine
- 换上: 将goroutine由非运行状态转换为运行状态,并促使其中其中的代码在某个GPU上运行
- 换下: 使一个goroutine中的代码中断执行,并让它的运行状态转换为非运行状态
原子操作有哪些?
sync/atomic包中函数可以做的原子操作有:加法(add)、比较并交换(cas)、加载(load)、存储(store)和交换(cap)
- 原子操作函数需要的是被操作值的指针,而不是值本身
- 原子加法操作函数可以做原子减法操作
sync/atomic.Value
- atomic.Value 属于结构体类型,结构体类型属于值类型
- 不能使用原子值存贮nil
- 向原子值存储的第一个值,决定它以后能且只能存储哪一个类型的值
- 如果有可能的话最好将原子值存储到结构体中,这样可以通过验证类型以防存储的原子操作因为类型报错
- 尽量不要向原子值存储引用类型的值 (如切片、字典、通道是引用类型的值),造成安全漏洞
package main
import (
"fmt"
"reflect"
"os"
"sync/atomic"
"errors"
"io"
)
func main() {
demo()
}
func demo() {
// Demo 1
fmt.Println("Demo 1")
var box atomic.Value
fmt.Println("Copy box to box2")
box2 := box
v1 := [...]int{1,2,3}
fmt.Printf("Store %v to box.\n", v1)
box.Store(v1)
fmt.Printf("The value load from box is %v.\n", box.Load())
fmt.Printf("The value load from box2 is %v.\n", box2.Load())
fmt.Println()
// Demo 2
v2 := "123"
fmt.Printf("Store %q to box2.\n", v2)
box2.Store(v2)
fmt.Printf("The value load from box is %v.\n", box.Load())
fmt.Printf("The value load from box2 is %v.\n", box2.Load())
fmt.Println()
// Demo 3
fmt.Println("Copy box to box3.")
box3 := box
fmt.Printf("The value load from box3 is %v.\n", box3.Load())
v3 := 123
fmt.Printf("Store %d to box2.\n", v3)
// box3.Store(v3)
_ = box3
fmt.Println()
// Demo4
var box4 atomic.Value
v4 := errors.New("something wrong")
fmt.Printf("Store an error with message %q to box4.\n", v4)
box4.Store(v4)
v41 := io.EOF
fmt.Println("Store a value of the same type to box4.")
box4.Store(v41)
v42, ok := interface{}(&os.PathError{}).(error)
if ok {
fmt.Printf("Store a value of type %T that implements error interface to box4.\n", v42)
// box4.Store(v42)
}
fmt.Println()
// Demo5
fmt.Println("Demo5")
box5, err := NewAtomicValue(v4)
if err != nil {
fmt.Printf("error: %s\n", err)
}
fmt.Printf("The legal type n box5 is %s.\n", box5.TypeOfValue())
fmt.Println("Store a value of the same type to box5.")
err = box5.Store(v41) // 将原子值存储到结构体中,自定义存储操作
if err != nil {
fmt.Printf("error: %s\n", err)
}
fmt.Printf("Store a value of type %T that implemetns error interface to box5.\n", v42)
err = box5.Store(v42)
if err != nil {
fmt.Printf("errors: %s\n", err)
}
fmt.Println()
// Demo6
fmt.Println("Demo6")
var box6 atomic.Value
v6 := []int{1,2,3}
fmt.Printf("Store %v to box6.\n", v6)
box6.Store(v6)
v6[1] = 4 // 造成安全漏洞
fmt.Printf("The value load from box6 is %v.\n", box6.Load())
v6 = []int{1,2,3}
store := func(v []int) {
replica := make([]int, len(v))
copy(replica, v)
box6.Store(replica)
}
fmt.Printf("Store %v to box6.\n", v6)
store(v6)
v6[2] = 5
fmt.Printf("The value load from box6 is %v.\n", box6.Load())
}
type atomicValue struct {
v atomic.Value
t reflect.Type
}
func NewAtomicValue(example interface{}) (*atomicValue, error){
if example == nil {
return nil, errors.New("atomic value: nil example")
}
return &atomicValue{
t: reflect.TypeOf(example),
}, nil
}
func (av *atomicValue) Store(v interface{}) error {
if v == nil {
return errors.New("atomic value: nil value")
}
t := reflect.TypeOf(v)
if t != av.t {
return fmt.Errorf("atomic value: wrong type: %s", t)
}
av.v.Store(v)
return nil
}
func (av *atomicValue) Load() interface{} {
return av.v.Load()
}
func (av *atomicValue) TypeOfValue() reflect.Type {
return av.t
}