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


    代码大致如下

    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的时候,这个循环几乎不会结束。

    教训:

    • 产生任务的生产者,对协程数量做检查,并进行等待,是对的;但是执行具体任务的协程一定要在确定的时间内结束,任何可能陷入永远循环的地方都要避免;
    • 如果一定要等待,设定一个超时时间,不能无限等待;
    • 最好加上监控计数,当某个位置卡死的时候,能够快速定位到。
  • 相关阅读:
    git 学习笔记
    参看gitlab版本号
    PHP7.1安装xdebug
    言不由衷
    容器镜像上传和下载
    利用docker搭建ubuntu+nginx+PHP容器
    生产者消费者模式(转)
    白盒测试以及基路径法测试
    分页的简单实现
    排列2(全排列next_permutation 注意格式)
  • 原文地址:https://www.cnblogs.com/ahfuzhang/p/13080918.html
Copyright © 2020-2023  润新知