go从语言层面就支持并行程序设计
goroutine(Go语言并行设计的核心),比thread高效易用
package main import( "fmt" "runtime" ) func say(word string){ for i:=0; i<10; i++ { // runtime.Gosched() //让出时间片 fmt.Println(word) } } func main(){ //默认系统线程数量为1,可通过下面指令调整,充分利用多核优势 runtime.GOMAXPROCS(4) go say("Hello") say("World") }
多个 goroutine 运行在同一个进程里面,共享内存数据,不过设计上我们要遵循:不要通过共享来通信,而要通过通信来共享
go提供了channel作为数据通信,类似unix下的管道,需要用make定义通信数据类型
package main import( "fmt" "runtime" ) //send函数读取channel时不会读取到自己发送到channel的数据 func send(name string,c chan string){ w := "Hello " + name //send message w to channel c c <- w //recv message from c w = <- c fmt.Printf("A Got %v from recv\n",w) } func recv(c chan string){ //recv message from c w := <- c fmt.Printf("B Got %v from send\n",w) //send message to c c <- "OK." } func main(){ runtime.GOMAXPROCS(4) c := make(chan string) go send("B",c) //go recv(c) res := "" fmt.Scan(&res) }
channel 接收和发送数据都是阻塞的,除非另一端已经准备好,这样就使得Goroutines 同步变的更加的简单,而不需要显式的 lock。
有缓冲的channel
ch := make(chan type, value)
value == 0 ! 无缓冲(阻塞)
value > 0 ! 缓冲(非阻塞,直到 value 个元素)
生产者通过关键字 close 函数关闭 channel,关闭channel 之后就无法再发送任何数据了,在消费方可以通过语法 v, ok := <-ch 测试 channel是否被关闭。如果 ok 返回 false,那么说明 channel 已经没有任何数据并且已经被关闭。
通过select在多个channel之间随机选择一个处理
package main import( "fmt" ) func main(){ chan_a := make(chan string) chan_b := make(chan string) chan_quit := make(chan string) go func() { //从chan_a通道接收数据五次,然后发送quit命令 for i:=0;i<5;i++ { fmt.Println("Listen on chan_a",<-chan_a) } chan_quit <- "quit" }() go func() { //同上 for i:=0;i<5;i++ { fmt.Println("Listen on chan_b",<-chan_b) } chan_quit <- "quit" }() for { select { case chan_a <- "hello_a"://chan_a通道可写 fmt.Println("Send hello_a to chan_a") case chan_b <- "hello_b"://chan_b通道可写 fmt.Println("Send hello_b to chan_b") case <- chan_quit://chan_quit通道可读 fmt.Println("Quit") return //case <- time.After(5 * time.Second): //设置超时 //default: //当所有channel都阻塞时调用默认代码 } } }
有疑问加站长微信联系(非本文作者)