zoukankan      html  css  js  c++  java
  • 【犯傻经历】虽然用原子加减来限制协程总数,但是协程加上了永不退出的代码

    代码大致如下

    var coroutineCount int64 = 0
    const maxCoroutineCount = 4000
    const defaultSleepMs = 100
    
    func Inc(){
        atomic.AddInt64(&coroutineCount, 1)
    }
    
    func Dec(){
        atomic.AddInt64(&coroutineCount, -1)
    }
    
    func job1(){
        Inc()
        defer Dec()
        //do something
    }
    
    func job2(){
        Inc()
        defer Dec()
        //do something
        for {
            coroutineCount := atomic.LoadInt64(&coroutineCount)
            if coroutineCount>=maxCoroutineCount{
                time.Sleep(defaultSleepMs*time.Millisecond)
                continue
            }
            break
        }
        //do something
    }
    
    func genJob(){
        for {
            for {
                coroutineCount := atomic.LoadInt64(&coroutineCount)
                if coroutineCount>=maxCoroutineCount{
                    time.Sleep(defaultSleepMs*time.Millisecond)
                    continue
                }
                break
            }
            go job1()
            go job2()
        }
    }
    

    这样的代码一开始很好,跑几分钟后莫名的停止了。
    导致问题的代码是 job2()中的那个循环检查:

        for {
            coroutineCount := atomic.LoadInt64(&coroutineCount)
            if coroutineCount>=maxCoroutineCount{
                time.Sleep(defaultSleepMs*time.Millisecond)
                continue
            }
            break
        }
    

    原因是:某一瞬间如果协程的数量大于等于maxCoroutineCount的时候,这个循环几乎不会结束。

    教训:

    • 产生任务的生产者,对协程数量做检查,并进行等待,是对的;但是执行具体任务的协程一定要在确定的时间内结束,任何可能陷入永远循环的地方都要避免;
    • 如果一定要等待,设定一个超时时间,不能无限等待;
    • 最好加上监控计数,当某个位置卡死的时候,能够快速定位到。
  • 相关阅读:
    4.20 每日一练
    4.19 每日一练
    4.18 每日一练
    Python函数初
    Python的文件操作
    python购物车
    python深浅拷贝,集合以及数据类型的补充
    Python 代码块 小数据池
    Python字典
    Python 列表操作
  • 原文地址:https://www.cnblogs.com/ahfuzhang/p/13080918.html
Copyright © 2011-2022 走看看