多协程环境下编程的一些坑

分布式网络的作业写了三整天,今天晚上终于把扩展实验之前的部分的代码给调试通过了,这次应该是没有什么问题了。在调试这些分布式代码时遇到几个坑,记录一下下次写代码的时候要注意一下。(主要都是多线程环境下原子操作的一些坑)

1. 对同一变量在一个函数里的不同位置访问时得到的值可能不同 2. 对某一系统状态,在需要使用该状态时需要多次确认状态的值,否则容易产生错误。

具体的案例分析如下:

  • 原子操作的注意事项

    package main
    
    import "fmt"
    type A struct {
    	value int
    }
    
    func (a *A) demo() bool {
    	value1 := a.value
    
    	var value2 int
    	for i := range []int{1,2,3,4,5}{
    		value2 = i
    	}
    	value2 = a.value
    	return value1 == value2
    }
    
    func main() {
    	count := 0
    	demo_a := A{}
    	for demo_a.demo(){
    		demo_a.value = 1
    		go func(a *A){
    			a.value = 100
    		}(&demo_a)
    		demo_a.demo()
    		count++
    	}
    	fmt.Printf("%v\n",count)
    }
    
    // Result
    // [kunwu@localhost atomic]$ go run atomic.go 
    // 1456

     

  • 由于协程的存在,上面的demo函数在运行时会出现value1和value2不同的情况,这种情况下看不出什么问题,但是如果是下面的情况就会出现问题,循环的次数就会和预期不同。而且这种情况由于两段代码离得比较远,还没法用锁。

    msg.a := a.value
    //
    // Some code
    //
    for index:=0; index<a.value; index++ {
    	//
    	// Some code
    	//
    }

    我的想法是如果在函数里需要多次访问同一变量的化,最好在程序开始时就给把值用零时变量存起来,这样在使用的时候就不会有问题。

    还有一个小地方

    // goroutine1
    1. i++
    2. array[i] = value
    // goroutinue2
    1. a = array[i]

    在协程的环境下,若先执行goroutine1的1,之后执行goroutine2的1,之后再执行goroutine2的2,就会取出未赋值的值。这里可以使用加锁的方法来解决,不过还是c++里的办法比较好

    array[i++] = value

     

  • 系统状态的确认

    这个坑比较好理解,我就直接放伪代码了,原本的想法是启动一个定时器,等peer的回复时不断执行事件,在得到一定的回复时取消事件执行,但是在启动定时器的地方没有加状态判断,导致有些情况下先进行了Stop timer的操作,后才执行Start timer的操作,导致timer持续执行。我的解决办法是在Start timer的地方加上状态判断,比如这里可以加上a.count > B的判断。

    var A classA
    
    func request() {
    	for i in range(peers){
    		go func(a classA) {
    			if ok := sendRequest(); ok == true{
    				a.count++
    				if a.count > B {
    					// Stop the timer
    				}
    			}
    		}(a)
    	}
    	
    	// Start the timer
    }

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值