mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-08-12 05:33:04 +08:00
完成14.1
This commit is contained in:
@@ -76,10 +76,78 @@ runtime.GOMAXPROCS(*numCores)
|
|||||||
|
|
||||||
示例 14.1-[goroutine1.go](examples/chapter_14/goroutine1.go) 介绍了概念:
|
示例 14.1-[goroutine1.go](examples/chapter_14/goroutine1.go) 介绍了概念:
|
||||||
```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协程。
|
||||||
|
|
||||||
## 链接
|
## 链接
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user