Go面试系列:Goroutine为什么设计为没有ID?

GoroutineID 是什么

我们要知道,为什么大家会下意识的想去要 GoroutineID,下面引用 Go 语言圣经中的表述:

在大多数支持多线程的操作系统和程序语言中,当前的线程都有一个独特的身份(ID),并且这个身份信息可以以一个普通值的形式被很容易地获取到,典型的可以是一个 integer 或者指针值。这种情况下我们做一个抽象化的 thread-local storage(线程本地存储,多线程编程中不希望其它线程访问的内容)就很容易,只需要以线程的 ID 作为 key 的一个 map 就可以解决问题,每一个线程以其 ID 就能从中获取到值,且和其它线程互不冲突。

也就是指在常规的进程、线程中都有其 ID 的概念,我们可以在程序中通过 ID 来获取其他进程、线程中的数据,甚至是传输数据。就像一把钥匙一样,有了他干啥都可以。

GoroutineID 的概念也是类似的,也就是协程的 ID。我们下意识的就期望通过协程 ID 来进行跨协程的操作。

但,在 Go 语言中 GoroutineID 并没有显式获取的办法,这就要打个大大的疑惑了。

为什么没有 GoroutineID

为什么在 Go 语言中没有 GoroutineID 呢,是从一开始就没有的,还是,这样子设计的原因是什么呢?

其实 Go 语言在以前是有暴露方法去获取 GoroutineID 的,但在 Go1.4 后就把该方法给隐藏起来了,不建议大家使用。

也就是明面上没有 GoroutineID,是一个有意而为之的行为。原因是:根据以往的经验,认为 thread-local storage 存在被滥用的可能性,且带来许多不必要的复杂度

简单来讲,Andrew Gerrand 的回答是 ”thread-local storage 的成本远远超过了它们的收益。它们只是不适合 Go 语言。”

潜在的问题

  • 当 Goroutine 消失时:

    • 它的 Goroutine 本地存储将不会被 GC 化。(你可以得到 goid 的当前的 Goroutine,但你不能得到所有运行的 Goroutine 的列表)
  • 如果处理程序自己产生了新的 Goroutine 怎么办?

    • 新的 Goroutine 失去了对既有的 Goroutine 本地存储。虽然你可以保证自己的代码不会产生其他的 Goroutine。
    • 一般来说,你不能确保标准库或任何第三方代码不会这样做。
  • Go 应用程序的复杂度和心智负担等上升。

滥用的场景

有一个对外提供 HTTP 服务的 Go 应用,也就是 Web Server。Go HTTP Server 都是采取每次请求新起一个协程的方式。

假设可以通过 GoroutineID 进行跨协程操纵,那么就有可能出现我的 Goroutine,不一定是由 “我” 自己决定的。可能其他正在处理的 GoroutineB 悄悄摸摸的改了我这个 GoroutineA 的行为。

这就有可能导致一个灾难问题,就是出问题时,你不知道是谁动了你的奶酪。查起问题来简直就是一个灾难。

若是自己维护的模块清楚还起码知道这事,假设你的前同事刚好离职了,你又在熟悉代码,一出问题。这锅那是死死的扣在了你的头上了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值