美文网首页
golang 信道总结

golang 信道总结

作者: TimeMage | 来源:发表于2018-02-10 20:18 被阅读529次

信道channel 概念

一个可以阻塞程序运行的队列,使用于并发状态下的消息传递

信道阻塞总结

  • 同步信道(队列大小为0,接发消息立即阻塞)

    • 接收数和发送数不相等

      func err1() {
          c := make(chan int)
          c <- 0
      }
      func err2() {
          c := make(chan int)
          <-c
      }
      
    • 在同一线程接收和发送于同一个同步信道

      func err3() {
          c := make(chan int)
          c <- 0 // 在这一步线程被阻塞了,无法执行到下一步
          <-c
      }
      
  • 异步信道 (有缓冲区)

    • 发送数超过缓冲大小会阻塞

      func err4() {
          c := make(chan int, 1)
          c <- 0
          c <- 0
          <-c
          <-c
      }
      
    • 接收数大于发送数阻塞

      func err5() {
          c := make(chan int, 1)
          <-c
      }
      
    • 发送数大于接受数,但多的部分小于缓冲区容量不阻塞

      func ok1() {
          c := make(chan int, 1)
          c <- 0
      }
      
  • 关闭的信道

    • 再发送或关闭会panic

      func err6() {
          ch := make(chan int)
          close(ch)
          close(ch)
      }
      func err7() {
          ch := make(chan int)
          close(ch)
          ch <- 0
      }
      
    • 再读取

      func test3() {
          ch := make(chan int, 1)
          ch <- 3
          a := 1
          close(ch)
          a, ok := <-ch
          fmt.Println(a, ok)
      }
      //3 true
      func test2() {
          ch := make(chan int)
          close(ch)
          var a = 1
          a, ok := <-ch
          fmt.Println(a, ok)
      }
      //0 false
      
  • 其他情况

    • 在子线程产生死锁,但主线程不同步,程序依然会退出

      func main() {
          go err1()
      }
      

channel 遍历

+ 两种遍历方式

    不确定信道长度的话,发送完最好关闭信道
    ~~~go
    func loop(c chan int) {
        for i := 1; i < 10; i++ {
            c <- i
        }
        for i := 1; i < 1e8; i++ {
            i = i + i - i
        }
        c <- 10
        close(c)
    }
    func forchan(proc func(chan int)) {
        var c = make(chan int)
        go proc(c)
        for k := range c {
            fmt.Printf("%d ", k)
        }
        fmt.Println()
    }
    func whilechan(proc func(chan int)) {
        var c = make(chan int)
        go proc(c)
        for {
            if d, ok := <-c; ok {
                fmt.Printf("%d ", d)
                } else {
                    break
                }
            }
        fmt.Println()
    }
    func main() {
        forchan(loop)
        whilechan(loop)
    }
    ~~~
+ 遍历不清楚长度的channel,如果不close的化会造成死锁

多信道选择 for-select

语法很简单看书,实现机制不清楚,会不会产生死锁后议

相关文章

网友评论

      本文标题:golang 信道总结

      本文链接:https://www.haomeiwen.com/subject/ztshtftx.html