为了账号安全,请及时绑定邮箱和手机立即绑定

Go 通道是如何实现的?

Go 通道是如何实现的?

Go
慕雪6442864 2021-07-02 02:11:41
在(简要地)回顾了 Go 语言规范、有效的 Go 和 Go 内存模型之后,我仍然有点不清楚 Go 通道是如何在幕后工作的。它们是什么样的结构?它们的作用有点像线程安全队列/数组。它们的实现是否依赖于架构?
查看完整描述

3 回答

?
慕妹3146593

TA贡献1820条经验 获得超9个赞

频道的源文件(来自你的 go 源代码根)在/src/pkg/runtime/chan.go 中

hchan是通道的中心数据结构,带有发送和接收链表(持有指向它们的 goroutine 和数据元素的指针)和一个closed标志。有一个Lock在 runtime2.go 中定义的嵌入式结构,根据操作系统用作互斥锁(futex)或信号量。锁定实现在 lock_futex.go (Linux/Dragonfly/Some BSD) 或 lock_sema.go (Windows/OSX/Plan9/Some BSD) 中,基于构建标签。

通道操作都在这个chan.go文件中实现,所以你可以看到makechan、send和receive操作,以及select构造、close、len和cap内置。

要深入了解通道的内部工作原理,您必须阅读Dmitry Vyukov 本人撰写的Go 通道(Go 核心开发人员、goroutines、调度程序和通道等)。


查看完整回答
反对 回复 2021-07-05
?
杨魅力

TA贡献1811条经验 获得超6个赞

查看通道的一种更简单的方法是,您可能希望在等待条件完成时暂停程序,通常用于防止 RACE 条件,这意味着一个线程可能不会在另一个线程之前完成,然后后来的线程或代码依赖有时不完成。一个例子可能是,您有一个线程从数据库或其他服务器检索一些数据并将数据放入变量、切片或映射中,但由于某种原因它被延迟了。那么您就有一个使用该变量的进程,但由于它尚未初始化,或者尚未获得其数据。程序失败。所以一个简单的看代码方式如下: package main


import "fmt"


var doneA = make(chan bool)

var doneB = make(chan bool)

var doneC = make(chan bool)


func init() { // this runs when you program starts.

    go func() {

        doneA <- true  //Give donA true

    }()

}


func initB() { //blocking

    go func() {

        a := <- doneA  //will wait here until doneA is true

        // Do somthing here

        fmt.Print(a)

        doneB <- true //State you finished

    }()

}


func initC() {

    go func() {

        <-doneB // still blocking, but dont care about the value

        // some code here

        doneC <- true // Indicate finished this function

    }()

}


func main() {

    initB()

    initC()

}

所以希望这会有所帮助。不是上面选择的答案,但我相信应该有助于消除谜团。我想知道我是否应该提出问题并自我回答?


查看完整回答
反对 回复 2021-07-05
  • 3 回答
  • 0 关注
  • 242 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信