[Go 并发编程 | 青训营笔记]

58 阅读1分钟

协程

还没有写

协程通道Channel

还没有写

WaitGroup实现同步

还没有写

runtime包

还没有写

runtime.Gosched()

让当前的线程让出cpu,让其他子协程去运行

 package main
 ​
 import (
     "fmt"
 )
 ​
 func show(msg string) {
     for i := 0; i < 2; i++ {
         fmt.Printf("msg: %v\n", msg)
     }
 ​
 }
 ​
 func main() {
     go show("java")
 ​
     for i := 0; i < 2; i++ {
         // 让当前进程让出cup,让其它子协程去运行
         fmt.Printf("msg: %v\n", "GO")
     }
 }

runtime.Goexit()

退出进程

 package main
 ​
 import (
     "fmt"
     "runtime"
     "time"
 )
 ​
 func show() {
     for i := 0; i < 10; i++ {
         if i > 5 {
             runtime.Goexit() // 退出进程
         }
         fmt.Printf("msg: %v\n", i)
     }
 }
 ​
 func main() {
     go show()
     time.Sleep(time.Second)
 }
 ​

runtime.GOMAXPROCS()

可以设置使用的最大的CPU核心数

 package main
 ​
 import (
     "fmt"
     "runtime"
     "time"
 )
 ​
 //func show(msg string) {
 //  for i := 0; i < 10; i++ {
 //      if i > 5 {
 //          runtime.Goexit() // 退出进程
 //
 //      }
 //      fmt.Printf("msg: %v\n", i)
 //  }
 //
 //}
 ​
 func a() {
     for i := 0; i < 5; i++ {
         fmt.Printf("a: %v\n", i)
     }
 }
 ​
 func b() {
     for i := 0; i < 5; i++ {
         fmt.Printf("b: %v\n", i)
     }
 }
 ​
 func main() {
     //go show("java")
     fmt.Printf("%v\n", runtime.NumCPU())
     runtime.GOMAXPROCS(6)
     go a()
     go b()
 ​
     time.Sleep(2 * time.Second)
 }

Mutex互斥锁实现资源互斥

遍历Channel

  • 死循环加if判断
  • for-Range遍历
 package main
 ​
 func main() {
     c := make(chan int)
 ​
     go func() {
         defer close(c)
         for i := 0; i < 5; i++ {
             c <- i
         }
     }()
 ​
     // 1. for-range
     for i := range c {
         println(i)
     }
 ​
     // 2. for and if
     for {
         v, ok := <-c
         if ok {
             println(v)
         } else {
             break
         }
     }
 }
 ​

Select

  1. select是go中的一个控制结构,类似于switch语句,用于异步IO操作。select会监听case中的channel的读写操作,当channel读写操作为非阻塞的时候(即能读能写的时候),将触发相关操作

select中的case语句必须是对channel的操作

select中的default子句总是可以运行的

  1. 如果有多个case可以运行,那么select将会随机选择一个case语句执行,其他的不会执行
  2. 如果没有可以运行的case子句,且有default语句,那么就执行default语句
  3. 如果没有可以运行的case子句,且没有default语句,那么select将阻塞,直到某个case通道可用
 package main
 ​
 var chanint = make(chan int)
 var chanStr = make(chan string)
 ​
 func main() {
 ​
     go func() {
         chanint <- 1
         chanStr <- "hello"
         defer close(chanint)
         defer close(chanStr)
     }()
 ​
     for {
         select {
         case r := <-chanStr:
             println(r)
         case r := <-chanint:
             println(r)
         default:
             println("end...")
         }
 ​
     }
 }

在上面的代码中我们我们把两个通道都关闭之后,select就会一直去读他们的类型的0值,

如果我们没有把通道关闭,那么就会一直执行default语句,因为两个通道没有数据,但是没有关闭,处于阻塞状态

如果我们把default语句和close语句都注释掉,那么就会死循环