go语言三——并行
ciaos · · 4057 次点击 · · 开始浏览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都阻塞时调用默认代码
}
}
}
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
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都阻塞时调用默认代码
}
}
}