概述

8.png
Go基础学习 协程 - 图2

goroutine 可能切换的点

  • 非强占式
  • I/O ,select
  • channel
  • 等待锁
  • 调用函数
  • runtime.Gosched()

只是参考,不能保证切换
Go基础学习 协程 - 图3

代码channel

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func worker(id int, c chan int) {
  7. for n := range c {
  8. fmt.Printf("Worker %d received %c\n",
  9. id, n)
  10. }
  11. }
  12. func createWorker(id int) chan<- int {
  13. c := make(chan int)
  14. go worker(id, c)
  15. return c
  16. }
  17. func chanDemo() {
  18. var channels [10]chan<- int
  19. for i := 0; i < 10; i++ {
  20. channels[i] = createWorker(i)
  21. }
  22. for i := 0; i < 10; i++ {
  23. channels[i] <- 'a' + i
  24. }
  25. for i := 0; i < 10; i++ {
  26. channels[i] <- 'A' + i
  27. }
  28. time.Sleep(time.Millisecond)
  29. }
  30. func bufferedChannel() {
  31. c := make(chan int, 3)
  32. go worker(0, c)
  33. c <- 'a'
  34. c <- 'b'
  35. c <- 'c'
  36. c <- 'd'
  37. time.Sleep(time.Millisecond)
  38. }
  39. func channelClose() {
  40. c := make(chan int)
  41. go worker(0, c)
  42. c <- 'a'
  43. c <- 'b'
  44. c <- 'c'
  45. c <- 'd'
  46. close(c)
  47. time.Sleep(time.Millisecond)
  48. }
  49. func main() {
  50. fmt.Println("Channel as first-class citizen")
  51. chanDemo()
  52. fmt.Println("Buffered channel")
  53. bufferedChannel()
  54. fmt.Println("Channel close and range")
  55. channelClose()
  56. }

select 代码

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "time"
  6. )
  7. func generator() chan int {
  8. out := make(chan int)
  9. go func() {
  10. i := 0
  11. for {
  12. time.Sleep(
  13. time.Duration(rand.Intn(1500)) *
  14. time.Millisecond)
  15. out <- i
  16. i++
  17. }
  18. }()
  19. return out
  20. }
  21. func worker(id int, c chan int) {
  22. for n := range c {
  23. time.Sleep(time.Second)
  24. fmt.Printf("Worker %d received %d\n",
  25. id, n)
  26. }
  27. }
  28. func createWorker(id int) chan<- int {
  29. c := make(chan int)
  30. go worker(id, c)
  31. return c
  32. }
  33. func main() {
  34. var c1, c2 = generator(), generator()
  35. var worker = createWorker(0)
  36. var values []int
  37. tm := time.After(10 * time.Second)
  38. tick := time.Tick(time.Second)
  39. for {
  40. var activeWorker chan<- int
  41. var activeValue int
  42. if len(values) > 0 {
  43. activeWorker = worker
  44. activeValue = values[0]
  45. }
  46. select {
  47. case n := <-c1:
  48. values = append(values, n)
  49. case n := <-c2:
  50. values = append(values, n)
  51. case activeWorker <- activeValue:
  52. values = values[1:]
  53. case <-time.After(800 * time.Millisecond):
  54. fmt.Println("timeout")
  55. case <-tick:
  56. fmt.Println(
  57. "queue len =", len(values))
  58. case <-tm:
  59. fmt.Println("bye")
  60. return
  61. }
  62. }
  63. }

done代码

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. func doWork(id int,
  7. w worker) {
  8. for n := range w.in {
  9. fmt.Printf("Worker %d received %c\n",
  10. id, n)
  11. w.done()
  12. }
  13. }
  14. type worker struct {
  15. in chan int
  16. done func()
  17. }
  18. func createWorker(
  19. id int, wg *sync.WaitGroup) worker {
  20. w := worker{
  21. in: make(chan int),
  22. done: func() {
  23. wg.Done()
  24. },
  25. }
  26. go doWork(id, w)
  27. return w
  28. }
  29. func chanDemo() {
  30. var wg sync.WaitGroup
  31. var workers [10]worker
  32. for i := 0; i < 10; i++ {
  33. workers[i] = createWorker(i, &wg)
  34. }
  35. wg.Add(20)
  36. for i, worker := range workers {
  37. worker.in <- 'a' + i
  38. }
  39. for i, worker := range workers {
  40. worker.in <- 'A' + i
  41. }
  42. wg.Wait()
  43. }
  44. func main() {
  45. chanDemo()
  46. }

image.jpeg