diff --git a/eBook/14.2.md b/eBook/14.2.md index 1f4f17e..1d01f80 100644 --- a/eBook/14.2.md +++ b/eBook/14.2.md @@ -249,7 +249,7 @@ go sum(bigArray, ch) // bigArray puts the calculated sum on ch sum := <- ch // wait for, and retrieve the sum ``` -也可以使用通道来达到同步的目的,这个很有效的用法在传统计算机中成为(semaphore)。或者换个方式:通过通道发送信号告知处理已经完成(在协程中)。 +也可以使用通道来达到同步的目的,这个很有效的用法在传统计算机中称为信号量(semaphore)。或者换个方式:通过通道发送信号告知处理已经完成(在协程中)。 在其他协程运行时让 main 程序无限阻塞的通常做法是在 `main` 函数的最后放置一个{}。 @@ -274,7 +274,7 @@ func main(){ } ``` -这个信号也可以是其他的,不反回结果,比如下边这个协程中的 lambda 函数协程: +这个信号也可以是其他的,不返回结果,比如下面这个协程中的匿名函数(lambda)协程: ```go ch := make(chan int) @@ -302,7 +302,7 @@ go doSort(s[i:]) <-done ``` -下边的代码,用完整的信号量模式对 size 长度的 gloat64 切片进行了 N 个` doSomething()` 计算并同时完成,通道 sem 分配了相同的长度(切包含空接口类型的元素),待所有的计算都完成后,发送信号(通过放入值)。在循环中从通道 sem 不停的接收数据来等待所有的协程完成。 +下边的代码,用完整的信号量模式对长度为N的 float64 切片进行了 N 个` doSomething()` 计算并同时完成,通道 sem 分配了相同的长度(切包含空接口类型的元素),待所有的计算都完成后,发送信号(通过放入值)。在循环中从通道 sem 不停的接收数据来等待所有的协程完成。 ```go type Empty interface {} @@ -343,11 +343,11 @@ for i, v := range data { 信号量是实现互斥锁(排外锁)常见的同步机制,限制对资源的访问,解决读写问题,比如没有实现信号量的 `sync` 的 Go 包,使用带缓冲的通道可以轻松实现: -- 带缓冲通道的容量和我们要同步的资源容量相同 -- 通道的长度(当前存放的元素个数)当前资源被使用的数量相同 +- 带缓冲通道的容量和要同步的资源容量相同 +- 通道的长度(当前存放的元素个数)与当前资源被使用的数量相同 - 容量减去通道的长度就是未处理的资源个数(标准信号量的整数值) -不用管通道中存放的是什么,只关注长度;因此我们创建了一个有长度变量为 0(字节)的通道: +不用管通道中存放的是什么,只关注长度;因此我们创建了一个长度可变但容量为0(字节)的通道: ```go type Empty interface {} @@ -403,7 +403,7 @@ func (s semaphore) Signal() { 习惯用法:通道工厂模式 -编程中常见另外一种模式如下:不将通道作为参数传递给协程,而用函数来生成一个通道并返回(工厂角色);函数内有个 lambda 函数被协程调用。 +编程中常见的另外一种模式如下:不将通道作为参数传递给协程,而用函数来生成一个通道并返回(工厂角色);函数内有个匿名函数被协程调用。 在 [channel_block2.go](examples/chapter_14/channel_block2.go) 加入这种模式便有了示例 14.5-[channel_idiom.go](examples/chapter_14/channel_idiom.go): diff --git a/eBook/14.4.md b/eBook/14.4.md index d241add..6d1647e 100644 --- a/eBook/14.4.md +++ b/eBook/14.4.md @@ -1,6 +1,6 @@ # 14.4 使用select切换协程 -从不不同的并发执行的协程中获取值可以通过关键字`select`来完成,它和`switch`控制语句非常相似(章节5.3)也被称作通信开关;它的行为像是“你准备好了吗”的轮询机制;`select`监听进入通道的数据,也可以是用通道发送值的时候。 +从不同的并发执行的协程中获取值可以通过关键字`select`来完成,它和`switch`控制语句非常相似(章节5.3)也被称作通信开关;它的行为像是“你准备好了吗”的轮询机制;`select`监听进入通道的数据,也可以是用通道发送值的时候。 ```go select { case u:= <- ch1: @@ -14,7 +14,7 @@ default: // no value ready to be received ``` `default`语句是可选的;fallthrough行为,和普通的switch相似,是不允许的。在任何一个case中执行`break`或者`return`,select就结束了。 -`select`做得就是:选择处理列出的多个通信情况中的一个。 +`select`做的就是:选择处理列出的多个通信情况中的一个。 * 如果都阻塞了,会等待直到其中一个可以处理 * 如果多个可以处理,随机选择一个 * 如果没有通道操作可以处理并且写了`default`语句,它就会执行:`default`永远是可运行的(这就是准备好了,可以执行)。 @@ -157,7 +157,7 @@ func backend() { 另一种方式(但是不太灵活)就是(客户端)在`chRequest`上提交请求,后台协程循环这个通道,使用`switch`根据请求的行为来分别处理: ```go -func backent() { +func backend() { for req := range chRequest { switch req.Subjext() { case A1: // Handle case ...