说明
大量并发的操作有可能超出计算机的读写能力;所以最终完成后的,读取的操作未必是最终状态(最后一波数可能在CPU缓存里,没有刷到内存中)
code
/*
目标:大量并发发生,如何安全修改状态;以原子计数器(原子钟?)为例;
方法:var ato uint64; 大并发中,使用atomic.add修改,安全改变状态;
回顾:sync.WaitGroup使用; 1 定义var wg wg; 2 wg.add() 3 routine:wg.done() 4 main: wg.wait()
*/
package main
import (
"fmt"
"sync"
"sync/atomic"
"time"
)
func main() {
var ato uint64
var wg sync.WaitGroup
fmt.Println(ato)
s1 := time.Now()
for i := 0; i < 10000; i++ {
wg.Add(1)
go func() {
for j:= 0; j < 5; j ++ {
atomic.AddUint64(&ato, 2) //必须是取地址读,否则并发会乱
}
}()
if i <20{
fmt.Println("value i,j,ato",i, atomic.LoadUint64(&ato))
}
if i > 9989{
fmt.Println("value i,j,ato",i, atomic.LoadUint64(&ato))
}
wg.Done()
}
wg.Wait()
s2 := time.Now()
//time.Sleep(3 * time.Second)
fmt.Println("完成所有计数,最终值为: ", atomic.LoadUint64(&ato), " 时间: ", s2.Sub(s1))
}
- 注释雕倒数第三行,并发后立刻读,在我得8核联想PC上发现
result:
0
value i,j,ato 0 0
value i,j,ato 1 0
value i,j,ato 2 0
value i,j,ato 3 0
value i,j,ato 4 0
value i,j,ato 5 0
value i,j,ato 6 0
value i,j,ato 7 0
value i,j,ato 8 0
value i,j,ato 9 0
value i,j,ato 10 80
value i,j,ato 11 110
value i,j,ato 12 110
value i,j,ato 13 110
value i,j,ato 14 110
value i,j,ato 15 110
value i,j,ato 16 110
value i,j,ato 17 110
value i,j,ato 18 110
value i,j,ato 19 180
value i,j,ato 9990 99888
value i,j,ato 9991 99910
value i,j,ato 9992 99910
value i,j,ato 9993 99910
value i,j,ato 9994 99930
value i,j,ato 9995 99940
value i,j,ato 9996 99960
value i,j,ato 9997 99970
value i,j,ato 9998 99970
value i,j,ato 9999 99980
完成所有计数,最终值为: 99990
打开最终延迟,等3秒再读数
time.Sleep(3 * time.Second)
…
value i,j,ato 9998 99960
value i,j,ato 9999 99960
完成所有计数,最终值为: 100000 时间: 3.9891ms