进程同步问题---golang模拟+打桩测试

通过设计俩函数,对全局变量自增和自减10000次来重现并发不加锁带来的问题,代码如下,Test

package main

import (
	"fmt"
	"time"
)
var i =1
func Test()int{
	go add()
	go dec()
	// sleep 1s,阻塞主协程保证俩协程有足够的执行时间
	time.Sleep(1*time.Second)
	// 正常情况下,i自增和自减10000次后,最后i的值应该不会发生改变,这里预期应该是1,但结果并不是
	fmt.Println(i)
	return i
}
//对全局变量i自减10000次
func dec()  {
	for j:=0;j<10000;j++{
		i--
	}
}

//对全局变量i自增10000次
func add(){
	for j:=0;j<10000;j++{
		i++
	}
}

下面benchmark 10次看看效果,测试用例如下:执行go test -v -bench=".*"

package main

import (
	"testing"
)

func Benchmark_TimeConsumingFunction(b *testing.B) {
	b.StopTimer() //调用该函数停止压力测试的时间计数

	//做一些初始化的工作,例如读取文件数据,数据库连接之类的,
	//这样这些时间不影响我们测试函数本身的性能

	b.StartTimer() //重新开始时间

	b.N=10 //自定义执行10次

	// 执行10次Test(),即重复10次自增自减
	for i := 0; i < b.N; i++ {
		ret:=Test()
		if ret!=1{
			b.Errorf("fail")
		}
	}
}

10次跑的结果如下,为什么会出现这种情况?

因为++,--操作虽然只有一句,但对计算机来说,并不是原子操作,编译的时候代码会变成3步,register=i, register=register+1,

i=register,如果有多个进程或者协程,都执行i++,或者i--操作,在这三步里就会穿插执行这些语句,就会造成不可预知的结果,因此为了避免这种情况,在并发读写时,需要加锁,这样,就可以保证三步执行期间不会引入新的语句

1
1
1
-4136
-4201
-6522
-6855
-4380
-4380
-1129
--- FAIL: Benchmark_TimeConsumingFunction
    pcb_test.go:20: fail
    pcb_test.go:20: fail
    pcb_test.go:20: fail
    pcb_test.go:20: fail
    pcb_test.go:20: fail
    pcb_test.go:20: fail
    pcb_test.go:20: fail
FAIL
exit status 1
FAIL    github.com/Altruiste1/ctest     10.323s

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值