go语言三——并行

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都阻塞时调用默认代码
                }      
        }      
} 

本文来自:ITEYE博客

感谢作者:ciaos

查看原文:go语言三——并行

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。