@@ -9,7 +9,7 @@ Goroutines是Go并行设计的核心。Goroutines说到底其实就是线程,
99Goroutines是通过Go的runtime管理的一个线程管理器。Goroutines通过` go ` 关键字实现了,其实就是一个普通的函数。
1010
1111	go hello(a, b, c) 
12- 	 
12+ 
1313通过关键字go就启动了一个Goroutines。我们来看一个例子
1414
1515	package main 
@@ -29,8 +29,8 @@ Goroutines是通过Go的runtime管理的一个线程管理器。Goroutines通过
2929	func main() { 
3030		go say("world") //开一个新的Goroutines执行 
3131		say("hello") //当前Goroutines执行 
32- 	}	  
33- 	 
32+ 	} 
33+ 
3434	输出: 
3535	hello 
3636	world 
@@ -41,7 +41,7 @@ Goroutines是通过Go的runtime管理的一个线程管理器。Goroutines通过
4141	hello 
4242	world 
4343	hello 
44- 	 
44+ 
4545我们可以看到go关键字很方便的就实现了并发编程。
4646##channels
4747Goroutines运行在相同的地址空间,因此访问共享内存必须做好同步。那么Goroutines之间如何进行数据的通信呢,Go提供了一个很好的通信机制channel。channel可以与Unix shell 中的双向管道做类比:可以通过它发送或者接收值。这些值只能是特定的类型:channel类型。定义一个channel 时,也需要定义发送到channel 的值的类型。注意,必须使用make 创建channel:
@@ -68,15 +68,15 @@ channel通过操作符`<-`来接收和发送数据
6868		} 
6969		c <- sum  // send sum to c 
7070	} 
71- 	 
71+ 
7272	func main() { 
7373		a := []int{7, 2, 8, -9, 4, 0} 
74- 	 
75- 	     c := make(chan int)
74+ 
75+ 		 c := make(chan int)
7676		go sum(a[:len(a)/2], c) 
7777		go sum(a[len(a)/2:], c) 
78- 	     x, y := <-c, <-c  // receive from c
79- 	 
78+ 		 x, y := <-c, <-c  // receive from c
79+ 
8080		fmt.Println(x, y, x + y) 
8181	} 
8282
@@ -86,9 +86,9 @@ channel通过操作符`<-`来接收和发送数据
8686上面我们介绍了默认的非缓存类型的channel,不过Go也允许指定channel的缓冲大小,很简单,就是channel可以存储多少元素。ch:= make(chan bool, 4),创建了可以存储4个元素的bool 型channel。在这个channel 中,前4个元素可以无阻塞的写入。当写入第5个元素时,代码将会阻塞,直到其他goroutine从channel 中读取一些元素,腾出空间。
8787
8888	ch := make(chan type, value) 
89- 	 
89+ 
9090	value == 0 ! 无缓冲(阻塞) 
91- 	value > 0 ! 缓冲(非阻塞,直到value 个元素)	  
91+ 	value > 0 ! 缓冲(非阻塞,直到value 个元素) 
9292
9393我们看一下下面这个例子,你可以在自己本机测试一下,修改相应的value值
9494
@@ -103,32 +103,32 @@ channel通过操作符`<-`来接收和发送数据
103103		c <- 2 
104104		fmt.Println(<-c) 
105105		fmt.Println(<-c) 
106- 	}	  
106+ 	} 
107107
108108##Range和Close
109109上面这个例子中,我们需要读取两次c,这样不是很方便,Go考虑到了这一点,所以也可以通过range,像操作slice或者map一样操作缓存类型的channel,请看下面的例子
110110
111111	package main 
112- 	 
112+ 
113113	import ( 
114114		"fmt" 
115115	) 
116- 	 
116+ 
117117	func fibonacci(n int, c chan int) { 
118- 	         x, y := 1, 1
119- 	         for i := 0; i < n; i++ {
120- 	                 c <- x
121- 	                 x, y = y, x + y
122- 	         }
123- 	         close(c)
118+ 			 x, y := 1, 1
119+ 			 for i := 0; i < n; i++ {
120+ 					 c <- x
121+ 					 x, y = y, x + y
122+ 			 }
123+ 			 close(c)
124124	} 
125- 	 
125+ 
126126	func main() { 
127- 	     c := make(chan int, 10)
127+ 		 c := make(chan int, 10)
128128		go fibonacci(cap(c), c) 
129- 	     for i := range c {
130- 	          fmt.Println(i)
131- 	     }
129+ 		 for i := range c {
130+ 			  fmt.Println(i)
131+ 		 }
132132	} 
133133
134134` for i := range c ` 能够不断的读取channel里面的数据,直到该channel被显示的关闭。上面代码我们看到可以显示的关闭channel,生产者通过关键字` close ` 函数关闭channel。关闭channel之后就无法再发送任何数据了,在消费方可以通过语法` v, ok := <-ch ` 测试channel是否被关闭。如果ok返回false,那么说明channel已经没有任何数据并且已经被关闭。
@@ -143,24 +143,24 @@ channel通过操作符`<-`来接收和发送数据
143143` select ` 默认是阻塞的,只有当监听的channel中有发送或接收可以进行时才会运行,当多个channel都准备好的时候,select是随机的选择一个执行的。
144144
145145	package main 
146- 	 
146+ 
147147	import "fmt" 
148- 	 
148+ 
149149	func fibonacci(c, quit chan int) { 
150-           x, y := 1, 1
151-           for {
152-                   select {
153-                   case c <- x:
154-                             x, y = y, x + y
155-                   case <-quit:
150+ 	 	 x, y := 1, 1
151+ 	 	 for {
152+ 	 			 select {
153+ 	 			 case c <- x:
154+ 	 					   x, y = y, x + y
155+ 	 			 case <-quit:
156156			fmt.Println("quit") 
157-                           return
158-                   }
159-           }
157+ 	 					 return
158+ 	 			 }
159+ 	 	 }
160160	} 
161- 	 
161+ 
162162	func main() { 
163-      	c := make(chan int) 
163+ 	 	c := make(chan int) 
164164		quit := make(chan int) 
165165		go func() { 
166166			for i := 0; i < 10; i++ { 
@@ -188,5 +188,5 @@ channel通过操作符`<-`来接收和发送数据
188188   *  上一章: [ interface] ( < 2.6.md > ) 
189189   *  下一节: [ 总结] ( < 2.8.md > ) 
190190
191- ## LastModified    
191+ ## LastModified  
192192   *  $Id$
0 commit comments