原子操作

Go语言运行时调度系统会恰当安排所有goroutine的运行,在同一时刻,只可能有少数goroutine处于运行状态,并且这个数量只会与M的数量一致,而不会睡着G的增多而增多
_
为了公平起见,Golang调度器会频繁的换上或换下这些goroutine

  • 换上: 将goroutine由非运行状态转换为运行状态,并促使其中其中的代码在某个GPU上运行
  • 换下: 使一个goroutine中的代码中断执行,并让它的运行状态转换为非运行状态

**

原子操作有哪些?


sync/atomic包中函数可以做的原子操作有:加法(add)、比较并交换(cas)、加载(load)、存储(store)和交换(cap)

  • 原子操作函数需要的是被操作值的指针,而不是值本身
  • 原子加法操作函数可以做原子减法操作

sync/atomic.Value

  • atomic.Value 属于结构体类型,结构体类型属于值类型
  • 不能使用原子值存贮nil
  • 向原子值存储的第一个值,决定它以后能且只能存储哪一个类型的值
  • 如果有可能的话最好将原子值存储到结构体中,这样可以通过验证类型以防存储的原子操作因为类型报错
  • 尽量不要向原子值存储引用类型的值 (如切片、字典、通道是引用类型的值),造成安全漏洞
  1. package main
  2. import (
  3. "fmt"
  4. "reflect"
  5. "os"
  6. "sync/atomic"
  7. "errors"
  8. "io"
  9. )
  10. func main() {
  11. demo()
  12. }
  13. func demo() {
  14. // Demo 1
  15. fmt.Println("Demo 1")
  16. var box atomic.Value
  17. fmt.Println("Copy box to box2")
  18. box2 := box
  19. v1 := [...]int{1,2,3}
  20. fmt.Printf("Store %v to box.\n", v1)
  21. box.Store(v1)
  22. fmt.Printf("The value load from box is %v.\n", box.Load())
  23. fmt.Printf("The value load from box2 is %v.\n", box2.Load())
  24. fmt.Println()
  25. // Demo 2
  26. v2 := "123"
  27. fmt.Printf("Store %q to box2.\n", v2)
  28. box2.Store(v2)
  29. fmt.Printf("The value load from box is %v.\n", box.Load())
  30. fmt.Printf("The value load from box2 is %v.\n", box2.Load())
  31. fmt.Println()
  32. // Demo 3
  33. fmt.Println("Copy box to box3.")
  34. box3 := box
  35. fmt.Printf("The value load from box3 is %v.\n", box3.Load())
  36. v3 := 123
  37. fmt.Printf("Store %d to box2.\n", v3)
  38. // box3.Store(v3)
  39. _ = box3
  40. fmt.Println()
  41. // Demo4
  42. var box4 atomic.Value
  43. v4 := errors.New("something wrong")
  44. fmt.Printf("Store an error with message %q to box4.\n", v4)
  45. box4.Store(v4)
  46. v41 := io.EOF
  47. fmt.Println("Store a value of the same type to box4.")
  48. box4.Store(v41)
  49. v42, ok := interface{}(&os.PathError{}).(error)
  50. if ok {
  51. fmt.Printf("Store a value of type %T that implements error interface to box4.\n", v42)
  52. // box4.Store(v42)
  53. }
  54. fmt.Println()
  55. // Demo5
  56. fmt.Println("Demo5")
  57. box5, err := NewAtomicValue(v4)
  58. if err != nil {
  59. fmt.Printf("error: %s\n", err)
  60. }
  61. fmt.Printf("The legal type n box5 is %s.\n", box5.TypeOfValue())
  62. fmt.Println("Store a value of the same type to box5.")
  63. err = box5.Store(v41) // 将原子值存储到结构体中,自定义存储操作
  64. if err != nil {
  65. fmt.Printf("error: %s\n", err)
  66. }
  67. fmt.Printf("Store a value of type %T that implemetns error interface to box5.\n", v42)
  68. err = box5.Store(v42)
  69. if err != nil {
  70. fmt.Printf("errors: %s\n", err)
  71. }
  72. fmt.Println()
  73. // Demo6
  74. fmt.Println("Demo6")
  75. var box6 atomic.Value
  76. v6 := []int{1,2,3}
  77. fmt.Printf("Store %v to box6.\n", v6)
  78. box6.Store(v6)
  79. v6[1] = 4 // 造成安全漏洞
  80. fmt.Printf("The value load from box6 is %v.\n", box6.Load())
  81. v6 = []int{1,2,3}
  82. store := func(v []int) {
  83. replica := make([]int, len(v))
  84. copy(replica, v)
  85. box6.Store(replica)
  86. }
  87. fmt.Printf("Store %v to box6.\n", v6)
  88. store(v6)
  89. v6[2] = 5
  90. fmt.Printf("The value load from box6 is %v.\n", box6.Load())
  91. }
  92. type atomicValue struct {
  93. v atomic.Value
  94. t reflect.Type
  95. }
  96. func NewAtomicValue(example interface{}) (*atomicValue, error){
  97. if example == nil {
  98. return nil, errors.New("atomic value: nil example")
  99. }
  100. return &atomicValue{
  101. t: reflect.TypeOf(example),
  102. }, nil
  103. }
  104. func (av *atomicValue) Store(v interface{}) error {
  105. if v == nil {
  106. return errors.New("atomic value: nil value")
  107. }
  108. t := reflect.TypeOf(v)
  109. if t != av.t {
  110. return fmt.Errorf("atomic value: wrong type: %s", t)
  111. }
  112. av.v.Store(v)
  113. return nil
  114. }
  115. func (av *atomicValue) Load() interface{} {
  116. return av.v.Load()
  117. }
  118. func (av *atomicValue) TypeOfValue() reflect.Type {
  119. return av.t
  120. }