先来看看上一篇文章我们提到去掉
runtime.Gosched()
程序会变成什么样子。代码如下:package main import ( "fmt" //"runtime" ) func say(s string) { for i := 0; i < 5; i++ { //释放时间片 //runtime.Gosched() fmt.Println(s) } } func main() { go say("world") //开一个新的Goroutines执行 say("hello") //当前Goroutines执行 }
运行结果如下:
$ go run test.go hello hello hello hello hello
在上面的例子中,我们看到,
world
这个单词并没有被打印出来。是不是感觉很奇怪?明明开了goroutine,却没有执行。实际上,在运行的时候被go修饰的函数,会进入主线程以外的线程等待执行,但因为主线程后面没有动作需要执行了,main函数结束就退出了,而goroutine队列的程序还没来得及执行就被注销了。这个时候如果我们在最后加上time.Sleep(time.Second)
就可以看到world
被输出了。
结果如下:$ go run test.go hello hello hello hello hello world world world world world
看到这个你也许又冒出来要给疑问,为啥不是交替输出的?其实这是因为我们的机器太快了,还没等到下个调度,就已经执行完了。这个调度是go自动分配的,但我们可以通过上篇文章的
runtime.Gosched()
来手动释放,如果你把上面的i改成一个大点的数字,比如100000,这个时候你就能看到交替输出。好了,现在来看今天的内容吧——go channel(通道)。Go语言提倡“以通信作为手段来共享内存”。因此在Go routine中go语言提供了channel这个方式来共享内存。看下面的示意图。各个线程之间通过channel来共享内存。
现在对channel有了一个基本的概念,那它到底怎么用呢?看一个简单的示例:package main import ( "fmt" ) func main() { //定义一个通道messages messages := make(chan string) //开线程,向messages发送字符串 go func() { messages <- "ping" }() //主线程中读取messages msg := <-messages fmt.Println(msg) }
默认情况通道的读取是阻塞的,所以这里并没有看到Sleep函数或者Gosched函数。
输出结果如下$ go run test.go ping
channel遵循FIFO原则,已接受的元素会立即销毁。
今天的文章到这里就结束了,下一期我们接着讲channel。感谢各位的品鉴,关注公众号(cainiaopark)更多精彩内容等你来批阅。版权申明:练习代码出
https://gobyexample.com
。其他为本人翻译或者创作,不代表源文作者和网站的观点。扫描二维码获取更多编程和科普小知识。某人说天天发美女不发她,这是几个意思,所以今天。。。
查看原文:http://www.zoues.com/2016/10/20/golangchannel/
golang:channel
最新推荐文章于 2024-03-04 14:00:13 发布