From d6d551c52b57f53f9de9eabc5d34aa6a3049b5c5 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Sat, 19 Dec 2015 10:26:44 +0800 Subject: [PATCH 01/23] Update 15.4.md --- eBook/15.4.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/eBook/15.4.md b/eBook/15.4.md index e69de29..2b94078 100644 --- a/eBook/15.4.md +++ b/eBook/15.4.md @@ -0,0 +1,53 @@ +# 15.4 写一个简单的网页应用 + +下边的程序在端口8088上启动了一个网页服务器;`SimpleServer`会处理`/test1`url使它在浏览器输出`hello world`。`FormServer`会处理'/test2`url:如果url最初由浏览器请求,那么它就是一个`GET`请求,并且返回一个`form`常量,包含了简单的`input`表单,这个表单里有一个文本框和一个提交按钮。当在文本框输入一些东西并点击提交按钮的时候,会发起一个`POST`请求。`FormServer`中的代码用到了`switch`来区分两种情况。在`POST`情况下,使用`request.FormValue("inp")`通过文本框的`name`属性`inp`来获取内容,并写回浏览器页面。在控制台启动程序并在浏览器中打开url`http://localhost:8088/text2`来测试这个程序: + +示例 15.10 [simple_webserver.go](examples/chapter_15/simple_webserver.go) +```go +package main + +import ( + "io" + "net/http" +) + +const form = ` + +
+ + +
+ +` + +/* handle a simple get request */ +func SimpleServer(w http.ResponseWriter, request *http.Request) { + io.WriteString(w, "

hello, world

") +} + +func FormServer(w http.ResponseWriter, request *http.Request) { + w.Header().Set("Content-Type", "text/html") + switch request.Method { + case "GET": + /* display the form to the user */ + io.WriteString(w, form) + case "POST": + /* handle the form data, note that ParseForm must + be called before we can extract form data */ + //request.ParseForm(); + //io.WriteString(w, request.Form["in"][0]) + io.WriteString(w, request.FormValue("in")) + } +} + +func main() { + http.HandleFunc("/test1", SimpleServer) + http.HandleFunc("/test2", FormServer) + if err := http.ListenAndServe(":8088", nil); err != nil { + panic(err) + } +} +``` +注:当使用字符串常量表示html文本的时候,包含``对于让浏览器识别它收到了一个html非常重要。 + + From f7a500beeb59726c61d3514223c66fc49f43e4e2 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Sat, 19 Dec 2015 15:13:56 +0800 Subject: [PATCH 02/23] Update 15.4.md --- eBook/15.4.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/eBook/15.4.md b/eBook/15.4.md index 2b94078..141bca8 100644 --- a/eBook/15.4.md +++ b/eBook/15.4.md @@ -50,4 +50,10 @@ func main() { ``` 注:当使用字符串常量表示html文本的时候,包含``对于让浏览器识别它收到了一个html非常重要。 +更安全的做法是在处理器中使用`w.Header().Set("Content-Type", "text/html")`在写入返回之前将`header`的`content-type`设置为`text/html` +`content-type`会让浏览器认为它可以使用函数`http.DetectContentType([]byte(form))`来处理收到的数据 + +练习 15.6 [statistics.go] + +编写一个网页程序,可以让用户输入一连串的数字,然后将它们打印出来,计算出这些数字的均值和中值,就像下边这张截图一样 From 1839fbb15b31cb921139f3b8f8314360a8216200 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 22 Dec 2015 22:43:19 +0800 Subject: [PATCH 03/23] Update 15.4.md --- eBook/15.4.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eBook/15.4.md b/eBook/15.4.md index 141bca8..29cc6ec 100644 --- a/eBook/15.4.md +++ b/eBook/15.4.md @@ -56,4 +56,5 @@ func main() { 练习 15.6 [statistics.go] -编写一个网页程序,可以让用户输入一连串的数字,然后将它们打印出来,计算出这些数字的均值和中值,就像下边这张截图一样 +编写一个网页程序,可以让用户输入一连串的数字,然后将它们打印出来,计算出这些数字的均值和中值,就像下边这张截图一样: +![](../images/15.4_fig15.1.jpg?raw=true) From bd7efffa5c226520e34d5475bf34daacb6755867 Mon Sep 17 00:00:00 2001 From: glight2000 Date: Wed, 23 Dec 2015 09:04:50 +0800 Subject: [PATCH 04/23] add fig image 15.4_fig15.1.jpg --- images/15.4_fig15.1.jpg | Bin 0 -> 69265 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/15.4_fig15.1.jpg diff --git a/images/15.4_fig15.1.jpg b/images/15.4_fig15.1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2a527535ebf566f9f546964b4b2568d9442b14a3 GIT binary patch literal 69265 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 literal 0 HcmV?d00001 From f5740457a95a4af531a17618ca4579e980744e8a Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 11:40:15 +0800 Subject: [PATCH 05/23] Update 14.0.md --- eBook/14.0.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/eBook/14.0.md b/eBook/14.0.md index 6664eaa..cc6dbf8 100644 --- a/eBook/14.0.md +++ b/eBook/14.0.md @@ -1,2 +1,7 @@ # 14 协程(goroutine)与通道(channel) +就像21世纪编程语言期望的那样,Go内置了对程序(网络,客户端-服务器,分布式计算,参见[章节15](15.0.md))间通讯的支持并且提供了并发编程的支持。可以使程序同时运行不同的代码块,可能在不同的处理器甚至是不同的电脑上。为了构建并发程序,go提供了`goroutines`和`channels`基础模块。他们的实现需要语言自身的支持以及编译器和运行环境的支持。Go提供的垃圾回收器也为并发编程提供了便利。 + +不要通过共享内存来通信。取而代之的是通过通信来共享内存。 + +使通讯相互协调。 From e3b0c7ff7680296f525432d473766b3ce73d3a25 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 11:43:23 +0800 Subject: [PATCH 06/23] Update 14.0.md --- eBook/14.0.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/eBook/14.0.md b/eBook/14.0.md index cc6dbf8..18bb92c 100644 --- a/eBook/14.0.md +++ b/eBook/14.0.md @@ -5,3 +5,9 @@ 不要通过共享内存来通信。取而代之的是通过通信来共享内存。 使通讯相互协调。 + +## 链接 + +- [目录](directory.md) +- 上一节:[性能调试:分析并优化 Go 程序](13.10.md) +- 下一节:[并发,并行和携程](14.1.md) From 20e4b0121e4dddbdf14cb587d1c7b192289465b0 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 11:45:02 +0800 Subject: [PATCH 07/23] Create 14.1.md --- eBook/14.1.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 eBook/14.1.md diff --git a/eBook/14.1.md b/eBook/14.1.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/eBook/14.1.md @@ -0,0 +1 @@ + From 19dde85f8ed7bb552c2f3a8a7f15049536749bb2 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 11:47:30 +0800 Subject: [PATCH 08/23] Update 14.1.md --- eBook/14.1.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/eBook/14.1.md b/eBook/14.1.md index 8b13789..104cf11 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -1 +1,5 @@ +# 14.1 并发,并行和携程 +## 14.1.1 什么是携程 + +一个应用程序是运行在机器上的一个处理过程; From dada2595a65ed178cfd87ddaa6b168dbdcf53bcd Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 11:48:03 +0800 Subject: [PATCH 09/23] Update 14.1.md --- eBook/14.1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eBook/14.1.md b/eBook/14.1.md index 104cf11..3bd9f0b 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -1,5 +1,5 @@ -# 14.1 并发,并行和携程 +# 14.1 并发,并行和协程 -## 14.1.1 什么是携程 +## 14.1.1 什么是协程 一个应用程序是运行在机器上的一个处理过程; From 2c0adecd1c025fcf74201dda91c4baf30ee3129b Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 11:48:38 +0800 Subject: [PATCH 10/23] Update 14.0.md --- eBook/14.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eBook/14.0.md b/eBook/14.0.md index 18bb92c..c04ec8c 100644 --- a/eBook/14.0.md +++ b/eBook/14.0.md @@ -10,4 +10,4 @@ - [目录](directory.md) - 上一节:[性能调试:分析并优化 Go 程序](13.10.md) -- 下一节:[并发,并行和携程](14.1.md) +- 下一节:[并发,并行和协程](14.1.md) From a887e0b0361812e29ff5087a7e6957efe48093b4 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 14:36:42 +0800 Subject: [PATCH 11/23] Update 14.1.md --- eBook/14.1.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/eBook/14.1.md b/eBook/14.1.md index 3bd9f0b..6b0e7ca 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -2,4 +2,27 @@ ## 14.1.1 什么是协程 -一个应用程序是运行在机器上的一个处理过程; +一个应用程序是运行在机器上的一个进程;进程是一个运行在自己内存地址空间里的独立执行体。一个进程由一个或多个操作系统线程组成,这些线程其实是共享同一个内存地址空间的一起工作的执行体。几乎所有'正式'的程序都是多线程的,以便让用户或计算机不必等待,或者能够同时服务多个请求(如Web服务器),或增加性能和吞吐量(例如,通过对不同的数据集并行执行代码)。一个并发程序可以在一个处理器或者内核上使用多个线程来执行任务,但是只有在同一个程序在某一个时间点在多个些处理内核或处理器上同时执行的任务才是真正的并行。 + +并行是一种通过使用多处理器以提高速度的能力。所以并发程序可以是并行的,也可以不是。 + + +公认的,使用多线程的应用难以做到准确,最主要的问题是内存中的数据共享,它们会被多线程以无法预知的方式进行操作,导致一些无法重现或者随机的结果(称作`竞态`) + +!!不要使用全局变量或者共享内存,它们会给你的代码在并发运算的时候带来危险。 + +解决之道在于同步不同的线程,对数据加锁,这样同时就只有一个线程可以变更数据。在Go的标准库`sync`中有一些工具用来在低级别的代码中实现加锁;我们在章节[9.3](9.3.md)中讨论过这个问题。不过过去的软件开发经验告诉我们这会带来更高的复杂度,更容易使代码出错以及更低的性能,所以这个经典的方法明显不再适合现代多核/多处理器编程:"`thread-per-connection`"模型不够有效。 + +Go更倾向于其他的方式,在诸多比较合适的范式中,有个被称作`Communicating Sequential Processes(顺序通信处理)`(CSP, C. Hoare发明的)还有一个叫做`message passing-model(消息传递)`(已经运用在了其他语言中,比如Eralng)。 + +在Go中,应用程序并发处理的部分被称作`goroutines(协程)`,它可以进行更有效的并发运算。在协程和操作系统线程之间并无一对一的关系:协程是根据一个或多个线程的可用性,映射(多路复用,执行于)在他们之上的;协程调度器在Go运行时很好的完成了这个工作。 + +协程工作在相同的地址空间中,所以共享内存的方式一定是同步的;这个可以使用`sync`包来实现(参见章节[9.3](9.3.md)),不过我们很不鼓励这样做:Go使用`channels`来同步协程(可以参见[14.2](14.2.md)等章节) + + + +## 链接 + +- [目录](directory.md) +- 上一节:[性能调试:分析并优化 Go 程序](13.10.md) +- 下一节:[并发,并行和协程](14.1.md) From 1c8e145ea134bd62074d64fefc1bb068dd6e34b2 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 14:39:21 +0800 Subject: [PATCH 12/23] =?UTF-8?q?=E5=A2=9E=E5=8A=A015.1=20.2=20.3=20.4?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/directory.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/eBook/directory.md b/eBook/directory.md index f7121be..adfdb4d 100644 --- a/eBook/directory.md +++ b/eBook/directory.md @@ -138,6 +138,9 @@ - 第14章:[协程(goroutine)与通道(channel)](14.0.md) - 第15章:[网络、模版与网页应用](15.0.md) - 15.1 [tcp服务器](15.1.md) + - 15.2 [一个简单的web服务器](15.2.md) + - 15.3 [访问并读取页面数据](15.3.md) + - 15.4 [写一个简单的网页应用](15.4.md) ## 第四部分:实际应用 From e34e79fdd3834255a1ae7264f0fedb2bc156ac7f Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 14:40:35 +0800 Subject: [PATCH 13/23] Update README_gc.md --- README_gc.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README_gc.md b/README_gc.md index 113534c..765a8b6 100644 --- a/README_gc.md +++ b/README_gc.md @@ -34,3 +34,4 @@ Golang 编程:245386165 |2015-11-25|13.10 性能调试:分析并优化 Go 程序 |2015-12-10|15.0 15.1 15.2 |2015-12-12|15.3 +|2015-12-22|15.4 From fb4b800d873d0b131910e6f6a992c1608748ce18 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 14:58:15 +0800 Subject: [PATCH 14/23] =?UTF-8?q?=E5=A2=9E=E5=8A=A014.1=20.2=20.3=E7=9A=84?= =?UTF-8?q?=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/directory.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/eBook/directory.md b/eBook/directory.md index adfdb4d..20837dd 100644 --- a/eBook/directory.md +++ b/eBook/directory.md @@ -136,6 +136,9 @@ - 13.9 [用(测试数据)表驱动测试](13.9.md) - 13.10 [性能调试:分析并优化 Go 程序](13.10.md) - 第14章:[协程(goroutine)与通道(channel)](14.0.md) + - 14.1 [并发,并行和协程](14.1.md) + - 14.2 [使用通道进行协程间通信](14.2.md) + - 14.3 [协程同步:关闭通道-对加锁的通道进行测试](14.3.md) - 第15章:[网络、模版与网页应用](15.0.md) - 15.1 [tcp服务器](15.1.md) - 15.2 [一个简单的web服务器](15.2.md) From 7b62558d933dc53f7036f3fd71574ee157983036 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 15:01:07 +0800 Subject: [PATCH 15/23] Update directory.md --- eBook/directory.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eBook/directory.md b/eBook/directory.md index 20837dd..eac2c1d 100644 --- a/eBook/directory.md +++ b/eBook/directory.md @@ -138,7 +138,7 @@ - 第14章:[协程(goroutine)与通道(channel)](14.0.md) - 14.1 [并发,并行和协程](14.1.md) - 14.2 [使用通道进行协程间通信](14.2.md) - - 14.3 [协程同步:关闭通道-对加锁的通道进行测试](14.3.md) + - 14.3 [协程同步:关闭通道-对阻塞的通道进行测试](14.3.md) - 第15章:[网络、模版与网页应用](15.0.md) - 15.1 [tcp服务器](15.1.md) - 15.2 [一个简单的web服务器](15.2.md) From 12103c7a8da0d8f5aa12f10aa8d6aa89b61a42a0 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 15:31:04 +0800 Subject: [PATCH 16/23] Update 14.1.md --- eBook/14.1.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/eBook/14.1.md b/eBook/14.1.md index 6b0e7ca..0da1cde 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -19,6 +19,13 @@ Go更倾向于其他的方式,在诸多比较合适的范式中,有个被称 协程工作在相同的地址空间中,所以共享内存的方式一定是同步的;这个可以使用`sync`包来实现(参见章节[9.3](9.3.md)),不过我们很不鼓励这样做:Go使用`channels`来同步协程(可以参见[14.2](14.2.md)等章节) +当系统调用(比如等待I/O)阻塞协程时,其他协程会继续在其他线程上工作。协程的设计隐藏了许多线程创建和管理方面的复杂工作。 + +协程是轻量的,比线程更轻。它们痕迹非常不明显(使用少量的内存和资源):在堆中使用4K的堆内存就可以创建它们。因为创建非常廉价,必要的时候可以轻松创建并运行大量的协程(在同一个一个地址空间中100,000个连续的协程)。并且它们对堆进行了分割,从而动态的增加(或缩减)内存的使用;堆的管理是自动的,但不是由垃圾回收器管理的,而是在协程退出后自动释放。 + +协程可以运行在多个操作系统线程之间,也可以运行在线程之内,让你可以很小的内存占用就可以处理大量的任务。由于操作系统线程上的协程时间片,你可以使用少量的操作系统线程就能拥有任意多个提供服务的协程,而且Go运行时可以聪明的意识到哪些协程被阻塞了,暂时搁置它们并处理其他携程。 + + ## 链接 From 5882bf32afa56d463fa84cbaa0cd15e82d4cc8a6 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 17:10:32 +0800 Subject: [PATCH 17/23] Update 14.1.md --- eBook/14.1.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/eBook/14.1.md b/eBook/14.1.md index 0da1cde..ac9e6d9 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -21,11 +21,23 @@ Go更倾向于其他的方式,在诸多比较合适的范式中,有个被称 当系统调用(比如等待I/O)阻塞协程时,其他协程会继续在其他线程上工作。协程的设计隐藏了许多线程创建和管理方面的复杂工作。 -协程是轻量的,比线程更轻。它们痕迹非常不明显(使用少量的内存和资源):在堆中使用4K的堆内存就可以创建它们。因为创建非常廉价,必要的时候可以轻松创建并运行大量的协程(在同一个一个地址空间中100,000个连续的协程)。并且它们对堆进行了分割,从而动态的增加(或缩减)内存的使用;堆的管理是自动的,但不是由垃圾回收器管理的,而是在协程退出后自动释放。 +协程是轻量的,比线程更轻。它们痕迹非常不明显(使用少量的内存和资源):使用4K的栈内存就可以在堆中创建它们。因为创建非常廉价,必要的时候可以轻松创建并运行大量的协程(在同一个一个地址空间中100,000个连续的协程)。并且它们对栈进行了分割,从而动态的增加(或缩减)内存的使用;栈的管理是自动的,但不是由垃圾回收器管理的,而是在协程退出后自动释放。 协程可以运行在多个操作系统线程之间,也可以运行在线程之内,让你可以很小的内存占用就可以处理大量的任务。由于操作系统线程上的协程时间片,你可以使用少量的操作系统线程就能拥有任意多个提供服务的协程,而且Go运行时可以聪明的意识到哪些协程被阻塞了,暂时搁置它们并处理其他携程。 +存在两种并发方式:确定性的(明确定义排序)和非确定性的(加锁/互斥从而未定义排序)。Go的协程和通道理所当然的支持确定性的并发方式(例如通道具有一个sender和一个receiver)。我们会在章节[14.7](14.7.md)中使用一个常见的算法问题(工人问题)来对比两种处理方式。 +协程是通过使用关键字`go`调用(执行)一个函数或者方法来实现的(也可以是匿名或者lambda函数)。这样会在当前的计算过程中开始一个同时进行的函数,在相同的地址空间中并且分配了独立的栈,比如:`go sum(bigArray)`// 在后台计算总和 + +协程的栈会根据需要进行伸缩,不出现栈溢出;开发者不需要关心栈的大小。当协程结束的时候,它会静默退出:用来启动这个协程的函数不会得到任何的返回值。 + +任何Go程序都必须有的`main()`函数也可以看做是一个协程,尽管它并没有通过`go`来启动。协程可以在程序初始化的过程中运行(在`init()`函数中)。 + +在一个协程中,比如它需要进行非常密集的运算,你可以在运算循环中周期的使用`runtime.Gosched()`:这会让出处理器,允许运行其他协程;它并不会使当前协程挂起,所以它会自动恢复执行。使用`Gosched()`可以使计算均匀分布,使通信不至于迟迟得不到响应。 + +## 14.1.2 并发和并行的差异 + +Go的并发原语提供了良好的并发设计基础: ## 链接 From de9a7c7f5d7b92a9819997bfa1056a1ebd44fa36 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 17:37:53 +0800 Subject: [PATCH 18/23] Update 14.1.md --- eBook/14.1.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/eBook/14.1.md b/eBook/14.1.md index ac9e6d9..86c2b76 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -37,7 +37,15 @@ Go更倾向于其他的方式,在诸多比较合适的范式中,有个被称 ## 14.1.2 并发和并行的差异 -Go的并发原语提供了良好的并发设计基础: +Go的并发原语提供了良好的并发设计基础:表达程序结构以便表示独立地执行的动作;所以Go的的重点不在于并行的首要位置:并发程序可能是并行的,也可能不是。并行是一种通过使用多处理器以提高速度的能力。但往往是,一个设计良好的并发程序在并行方面的表现也非常出色。 + +在当前的运行时(2012年一月)实现中,Go默认没有并行指令,只有一个独立的核心或处理器被专门用于Go程序,不论它启动了多少个协程;所以这些协程是并发运行的,但他们不是并行运行的:同一时间只有一个协程会处在运行状态。 + +这个情况在以后可能会发生改变,不过届时,为了使你的程序可以使用多个核心运行,这时协程就真正的是并行运行了,你必须使用`GOMAXPROCS`变量。 + +这会告诉运行时有多少个协程同时执行。 + +并且只有gc编译器真正实现了协程,适当的把协程映射到操作系统线程。使用`gccgo`编译器,会为每一个协程创建操作系统线程。 ## 链接 From afeed5b8c1d98da6b67d851ba5828a306851356e Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 23 Dec 2015 19:47:38 +0800 Subject: [PATCH 19/23] Update 14.1.md --- eBook/14.1.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/eBook/14.1.md b/eBook/14.1.md index 86c2b76..23e13e4 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -47,6 +47,9 @@ Go的并发原语提供了良好的并发设计基础:表达程序结构以便 并且只有gc编译器真正实现了协程,适当的把协程映射到操作系统线程。使用`gccgo`编译器,会为每一个协程创建操作系统线程。 +## 14.1.3 使用GOMAXPROCS + +在gc编译器下(6g或者8g)你必须设置GOMAXPROCS为一个大于默认值1的数值来允许运行时支持使用多于1个的操作系统线程,所有的协程都会共享同一个线程除非将GOMAXPROCS设置为一个大于1的数。当GOMAXPROCS大于1时,会有一个线程池管理许多的线程。通过`gccgo`编译器GOMAXPROCS有效的与运行中的协程数量相等。假设n是机器上处理器或者核心的数量。如果你设置环境变量GOMAXPROCS>=n,或者执行`runtime.GOMAXPROCS(n)`,接下来协程会被分割(分散)到n个处理器上。 ## 链接 From 87eeba5bb28b13dc7dfd15081e48f5cba9aaebf6 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Thu, 24 Dec 2015 10:24:21 +0800 Subject: [PATCH 20/23] Update 14.1.md --- eBook/14.1.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/eBook/14.1.md b/eBook/14.1.md index 23e13e4..9f6987d 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -23,7 +23,7 @@ Go更倾向于其他的方式,在诸多比较合适的范式中,有个被称 协程是轻量的,比线程更轻。它们痕迹非常不明显(使用少量的内存和资源):使用4K的栈内存就可以在堆中创建它们。因为创建非常廉价,必要的时候可以轻松创建并运行大量的协程(在同一个一个地址空间中100,000个连续的协程)。并且它们对栈进行了分割,从而动态的增加(或缩减)内存的使用;栈的管理是自动的,但不是由垃圾回收器管理的,而是在协程退出后自动释放。 -协程可以运行在多个操作系统线程之间,也可以运行在线程之内,让你可以很小的内存占用就可以处理大量的任务。由于操作系统线程上的协程时间片,你可以使用少量的操作系统线程就能拥有任意多个提供服务的协程,而且Go运行时可以聪明的意识到哪些协程被阻塞了,暂时搁置它们并处理其他携程。 +协程可以运行在多个操作系统线程之间,也可以运行在线程之内,让你可以很小的内存占用就可以处理大量的任务。由于操作系统线程上的协程时间片,你可以使用少量的操作系统线程就能拥有任意多个提供服务的协程,而且Go运行时可以聪明的意识到哪些协程被阻塞了,暂时搁置它们并处理其他协程。 存在两种并发方式:确定性的(明确定义排序)和非确定性的(加锁/互斥从而未定义排序)。Go的协程和通道理所当然的支持确定性的并发方式(例如通道具有一个sender和一个receiver)。我们会在章节[14.7](14.7.md)中使用一个常见的算法问题(工人问题)来对比两种处理方式。 @@ -49,7 +49,13 @@ Go的并发原语提供了良好的并发设计基础:表达程序结构以便 ## 14.1.3 使用GOMAXPROCS -在gc编译器下(6g或者8g)你必须设置GOMAXPROCS为一个大于默认值1的数值来允许运行时支持使用多于1个的操作系统线程,所有的协程都会共享同一个线程除非将GOMAXPROCS设置为一个大于1的数。当GOMAXPROCS大于1时,会有一个线程池管理许多的线程。通过`gccgo`编译器GOMAXPROCS有效的与运行中的协程数量相等。假设n是机器上处理器或者核心的数量。如果你设置环境变量GOMAXPROCS>=n,或者执行`runtime.GOMAXPROCS(n)`,接下来协程会被分割(分散)到n个处理器上。 +在gc编译器下(6g或者8g)你必须设置GOMAXPROCS为一个大于默认值1的数值来允许运行时支持使用多于1个的操作系统线程,所有的协程都会共享同一个线程除非将GOMAXPROCS设置为一个大于1的数。当GOMAXPROCS大于1时,会有一个线程池管理许多的线程。通过`gccgo`编译器GOMAXPROCS有效的与运行中的协程数量相等。假设n是机器上处理器或者核心的数量。如果你设置环境变量GOMAXPROCS>=n,或者执行`runtime.GOMAXPROCS(n)`,接下来协程会被分割(分散)到n个处理器上。更多的处理器并不意味着性能的线性提升。有这样一个经验法则,对于n个核心的情况设置GOMAXPROCS为n-1以获得最佳性能,也同样需要遵守这条规则:协程的数量 > 1 + GOMAXPROCS > 1 + +所以如果在某一时间只有一个协程在执行,不要设置GOMAXPROCS! + +还有一些通过实验观察到的现象:在一台1颗CPU的笔记本电脑上,增加GOMAXPROCS到9会带来性能提升。在一台32核的机器上,设置GOMAXPROCS=8会达到最好的性能,在测试环境中,更高的数值无法提升性能。如果设置一个很大的GOMAXPROCS只会带来轻微的性能下降;设置GOMAXPROCS=100,使用“top”命令和“H”选项查看到只有7个活动的线程。 + + ## 链接 From 6e04c75a944b7dcf5b17d44f4ec554171a60f185 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Thu, 24 Dec 2015 10:52:02 +0800 Subject: [PATCH 21/23] Update 14.1.md --- eBook/14.1.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/eBook/14.1.md b/eBook/14.1.md index 9f6987d..220df5e 100644 --- a/eBook/14.1.md +++ b/eBook/14.1.md @@ -55,6 +55,30 @@ Go的并发原语提供了良好的并发设计基础:表达程序结构以便 还有一些通过实验观察到的现象:在一台1颗CPU的笔记本电脑上,增加GOMAXPROCS到9会带来性能提升。在一台32核的机器上,设置GOMAXPROCS=8会达到最好的性能,在测试环境中,更高的数值无法提升性能。如果设置一个很大的GOMAXPROCS只会带来轻微的性能下降;设置GOMAXPROCS=100,使用“top”命令和“H”选项查看到只有7个活动的线程。 +增加GOMAXPROCS的数值对程序进行并发计算是有好处的; + +请看[goroutine_select2.go](examples/chapter_14/goroutine_select2.go) + +总结:GOMAXPROCS等同于(并发的)线程数凉,在一台核心数多于1个的机器上,会尽可能有等同于核心数的线程在并行运行。 + +## 14.1.4 如何用命令行指定使用的核心数量 + +使用`flags`包,如下: +```go +var numCores = flag.Int("n", 2, "number of CPU cores to use") + +in main() +flag.Pars() +runtime.GOMAXPROCS(*numCores) +``` + +协程可以通过调用`runtime.Goexit()`来停止,尽管这样做几乎没有必要。 + +示例 14.1-[goroutine1.go](examples/chapter_14/goroutine1.go) 介绍了概念: +```go +``` + + ## 链接 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 22/23] =?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协程。 ## 链接 From 8e97b150001ea8a25692d4d32970b788445dd7bb Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Fri, 25 Dec 2015 09:30:22 +0800 Subject: [PATCH 23/23] Update 14.0.md --- eBook/14.0.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eBook/14.0.md b/eBook/14.0.md index c04ec8c..bf51abc 100644 --- a/eBook/14.0.md +++ b/eBook/14.0.md @@ -1,10 +1,10 @@ # 14 协程(goroutine)与通道(channel) -就像21世纪编程语言期望的那样,Go内置了对程序(网络,客户端-服务器,分布式计算,参见[章节15](15.0.md))间通讯的支持并且提供了并发编程的支持。可以使程序同时运行不同的代码块,可能在不同的处理器甚至是不同的电脑上。为了构建并发程序,go提供了`goroutines`和`channels`基础模块。他们的实现需要语言自身的支持以及编译器和运行环境的支持。Go提供的垃圾回收器也为并发编程提供了便利。 +作为一门21世纪的语言,Go 原生支持应用之间的通信(网络,客户端和服务端,分布式计算,参见 15 章)和程序的并发。程序可以在不同的处理器和计算机上同时执行不同的代码段。Go 语言为构建并发程序的基本代码块是 协程 (goroutine) 与通道 (channel)。他们需要语言,编译器,和runtime的支持。Go 语言提供的垃圾回收器对并发编程至关重要。 -不要通过共享内存来通信。取而代之的是通过通信来共享内存。 +*不要通过共享内存来通信,而通过通信来共享内存。* -使通讯相互协调。 +通信强制协作。 ## 链接