From 33b3655ccc8a2efe531c6587890bd7adcf659e82 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Thu, 24 Dec 2015 12:13:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=9014.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/14.1.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/eBook/14.1.md b/eBook/14.1.md index 220df5e..8bec9d7 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -76,10 +76,78 @@ runtime.GOMAXPROCS(*numCores) 示例 14.1-[goroutine1.go](examples/chapter_14/goroutine1.go) 介绍了概念: ```go +package main + +import ( + "fmt" + "time" +) + +func main() { + fmt.Println("In main()") + go longWait() + go shortWait() + fmt.Println("About to sleep in main()") + // sleep works with a Duration in nanoseconds (ns) ! + time.Sleep(10 * 1e9) + fmt.Println("At the end of main()") +} + +func longWait() { + fmt.Println("Beginning longWait()") + time.Sleep(5 * 1e9) // sleep for 5 seconds + fmt.Println("End of longWait()") +} + +func shortWait() { + fmt.Println("Beginning shortWait()") + time.Sleep(2 * 1e9) // sleep for 2 seconds + fmt.Println("End of shortWait()") +} ``` +输出 +``` +In main() +About to sleep in main() +Beginning longWait() +Beginning shortWait() +End of shortWait() +End of longWait() +At the end of main() // after 10s +``` +`main()`,`longWait()`和`shortWait()`三个函数作为独立的处理单元按顺序启动,然后开始并行运行。每一个函数都在运行的开始和结束阶段输出了消息。为了模拟他们运算的时间消耗,我们使用了`time`包中的`Sleep`函数。`Sleep()`可以按照指定的时间来暂停函数或协程的执行,这里使用了纳秒(ns,符号1e9表示1乘10的9次方,e=指数)。 +他们按照我们期望的顺序打印出了消息,几乎都一样,可是我们明白这是模拟出来的,以并行的方式。我们让`main()`函数暂停10秒从而确定它会在另外两个协程之后结束。如果不这样(如果我们让`main()`函数停止4秒),`main()`会提前结束,`longWait()`则无法完成。如果我们不在`main()`中等待,协程会随着程序的结束而消亡。 +当`main()`函数返回的时候,程序退出:它不会等待任何其他非main协程的结束。这就是为什么在服务器程序中,每一个请求都会启动一个协程来处理,`server()`函数必须保持运行状态。通常使用一个无限循环来达到这样的目的。 +另外,协程是独立的处理单元,一旦陆续启动一些协程,你无法确定他们是什么时候真正开始执行的。你的代码罗技必须具独立于协程调用的顺序。 + +为了对比使用一个线程,连续调用的情况,移除go关键字,重新运行程序。 + +现在输出: +``` +In main() +Beginning longWait() +End of longWait() +Beginning shortWait() +End of shortWait() +About to sleep in main() +At the end of main() // after 17 s +``` +协程更有用的一个例子应该是在一个非常长的数组中查找一个元素。 + +将数组分割为若干个不重复的切片,然后给每一个切片启动一个协程进行查找计算。这样许多并行的线程可以用来进行查找任务,整体的查找时间会缩短(除以协程的数量)。 + +## 14.1.5 Go协程(goroutines)和协程(coroutines) + +(译者注:标题中的“Go协程(goroutines)”即是14章讲的协程指的是go语言中的协程。而“协程(coroutines)”指的是其他语言中的协程概念,仅在本节出现。) + +在其他语言中,比如C#,Lua或者Python都有协程的概念。这个名字表明它和Go协程有些相似,不过有两点不同: +* go协程意味着并行(或者可以以并行的方式部署),协程一般来说不是这样的 +* go协程通过通道来通信;协程通过让出和恢复操作来通信 + +Go协程比协程更强大,也很容易从协程的逻辑复用到go协程。 ## 链接