go牛刀小试之原子计数: 大并发的奇怪问题,最终读取的数早一点读和晚一点可能不一样

24 篇文章 1 订阅
7 篇文章 0 订阅

说明

大量并发的操作有可能超出计算机的读写能力;所以最终完成后的,读取的操作未必是最终状态(最后一波数可能在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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值