并发 concurrency

-从源码解析来看, goroutine 只是由官方实现的超级 “线程池” 而已
-并发部署并行
-并发主要由切换时间片段来实现 “同时” 运行,并行则是直接利用多核实现多线程的运行,但 Go 可以设置使用核数,以发挥多核计算机的能力

  1. import (
  2. "fmt"
  3. "time"
  4. )
  5. func main() {
  6. go Go()
  7. //等待两秒
  8. time.Sleep(2 * time.Second)
  9. }
  10. func Go() {
  11. fmt.Println("Go Go Go!!!")
  12. }

goroutine 奉行通过通信来共享内存,而不是共享内存来通信

channel

-channelgoroutine 沟通的桥梁,大都是阻塞同步的
-通过 make 创建, close 关闭
-channel 时引用类型
-可以使用 for range 来迭代不断操作 channel
-可以设置单向或双向通道
-可以设置缓存大小,在未被填满前不会发生阻塞

  1. func main() {
  2. c := make(chan bool)
  3. go func() {
  4. fmt.Println("Go Go Go!!!")
  5. c <- true
  6. close(c)
  7. }()
  8. for v := range c {
  9. fmt.Println(v)
  10. }
  11. }

select

-可处理一个或多个 channel 的发送和接收
-同时有多个可用的 channel是按随机顺序处理
-可用空的 select 来阻塞 main 函数
-可设置超时

  1. func main() {
  2. c1, c2 := make(chan int), make(chan string)
  3. o := make(chan bool)
  4. go func() {
  5. for {
  6. select {
  7. case v, ok := <-c1:
  8. if !ok {
  9. o <- true
  10. break
  11. }
  12. fmt.Println("c1:",v)
  13. case v, ok := <-c2:
  14. if !ok {
  15. o <- true
  16. break
  17. }
  18. fmt.Println("c2:",v)
  19. }
  20. }
  21. }()
  22. c1 <- 1
  23. c2 <- "hi"
  24. c1 <- 3
  25. c2 <- "hello"
  26. close(c1)
  27. <-o
  28. }

select 发送

  1. func main() {
  2. c := make(chan int)
  3. go func() {
  4. for v := range c {
  5. fmt.Println(v)
  6. }
  7. }()
  8. for {
  9. select {
  10. case c <- 0:
  11. case c <- 1:
  12. }
  13. }
  14. }

select 设置超时

  1. import (
  2. "fmt"
  3. "time"
  4. )
  5. func main() {
  6. c := make(chan bool)
  7. select {
  8. case v:= <-c:
  9. fmt.Println(v)
  10. case <-time.After(3 * time.Second):
  11. fmt.Println("Timeout")
  12. }
  13. }

课后习题

  1. var c chan string
  2. func Pingpang() {
  3. i := 0
  4. for {
  5. fmt.Println(<-c)
  6. c <- fmt.Sprintf("From Pingpang: Hi, #%d", i)
  7. i++
  8. }
  9. }
  10. func main() {
  11. c = make(chan string)
  12. go Pingpang()
  13. for i := 0; i < 10; i++ {
  14. c <- fmt.Sprintf("From Pingpang: Hello, #%d", i)
  15. fmt.Println(<-c)
  16. }
  17. }