• Go并发编程之常见并发bug


     注意:下述所有图片中 - 号是BUG代码,+号是修复BUG的代码

    1.死锁

    goroutine1 ch发送者被阻塞住,无法释放锁

    goroutine2 loop获取锁失败

     

    2.goroutine永久泄露

     context.WithCancel内部启动goroutine,在ctx被覆盖后goroutin永久泄露

    3.waitgroup使用不当,永久阻塞

    使用WaitGroup一定要遵守的原则就是,等所有的Add方法调用之后再调用Wait否则可能导致panic或者不期望的结果

    4.闭包捕获本地变量

    5.goroutine启动前要保证waitgroup.Add完成

    6.多次关闭同一个channel

     关闭已经关闭的channel会导致panic,因此在并发编程中要处理好channel的关闭

    7.map 并发读写

    这个bug无法被recover

    线上做好supervisor和stderr重定向到文件,不然两眼一抹黑

    共享资源竞争的问题,非常复杂,并且难以察觉,好在 Go 为我们提供了一个工具帮助我们检查,这个就是go build -race 命令。在项目目录下执行这个命令,生成一个可以执行文件,然后再运行这个可执行文件,就可以看到打印出的检测信息。

    并发场景下考虑使用:sync.map

    8.不控制gouroutine数量

    这个例子实现了 math.MaxInt32 个协程的并发,约 2^31 = 2 亿个

    运行会直接导致:​panic: too many concurrent operations on a single file or socket (max 1048575)

    不同的应用程序,消耗的资源是不一样的。比较推荐的方式的是:应用程序来主动限制并发的协程数量。

    • 利用缓冲信道实现[2]

    • make(chan struct{}, 3) 创建缓冲区大小为 3 的 channel,在没有被接收的情况下,至多发送 3 个消息则被阻塞。
    • 开启协程前,调用 ch <- struct{}{},若缓存区满,则阻塞。
    • 协程任务结束,调用 <-ch 释放缓冲区。
    • sync.WaitGroup 并不是必须的,例如 http 服务,每个请求天然是并发的,此时使用 channel 控制并发处理的任务数量,就不需要 sync.WaitGroup。 

    References

    1.如何优雅地关闭通道

    2.Go高性能编程之并发编程

  • 相关阅读:
    汇编语言王爽第四版17.3完程可运行可调试
    Celery笔记七之定时任务及crontab定义
    腾讯算法实习面试总结
    连小白都在用的电子期刊制作网站
    智慧公厕有多智能?智慧厕所黑科技揭秘
    PySide6实现pdf转化为word和长图片
    Redis集群
    Mysql中DML操作数据(增,删,改)
    艾美捷MTT细胞增殖检测试剂盒说明书及文献引用
    IDC报告:国内游戏云市场,腾讯云用量规模位列第一
  • 原文地址:https://blog.csdn.net/qq_37186127/article/details/125530633