举个例子
func task1() {
for i := 0; i < 2; i++ {
fmt.Println("火车驶向云外")
}
}
func task2() {
for i := 0; i < 2; i++ {
fmt.Println("梦安魂于九霄")
}
}
func main() {
task1()
task2()
}
火车驶向云外
火车驶向云外
梦安魂于九霄
梦安魂于九霄
在这个例子中需要打印完task1再打印task2
接下来在每个函数前都加个go,启动两个goroutine来执行两个函数
func main() {
go task1()
go task2()
}
c:/go/bin/go.exe build [C:/Users/Wanglixue/go/src/map应用]
成功: 进程退出代码 0.
C:/Users/Wanglixue/go/src/map应用/map应用.exe [C:/Users/Wanglixue/go/src/map应用]
成功: 进程退出代码 0.
但结果却是什么也没打印,原因在于在程序启动时,Go程序就会为main()函数创建一个默认的goroutine。当main()函数返回的时候该goroutine就结束了,所有在main()函数中启动的goroutine会一同结束。也就是说main函数执行太快了,两个task函数还没开始执行程序就结束了
为了不让执行太快,让main函数等一等,需要用到Sleep函数(最简陋的方法)
func main() {
go task1()
go task2()
time.Sleep(time.Second * 6)//为了通过时间设置一个延迟
}
梦安魂于九霄
梦安魂于九霄
火车驶向云外
火车驶向云外
但此时先执行了task2,才执行了task1
func task1() {
for i := 0; i < 2; i++ {
fmt.Println("火车驶向云外")
time.Sleep(time.Second)
}
}
func task2() {
for i := 0; i < 2; i++ {
fmt.Println("梦安魂于九霄")
time.Sleep(time.Second)
}
}
func main() {
go task1()
go task2()
time.Sleep(time.Second * 6)
}
//执行顺序控制不了
火车驶向云外
梦安魂于九霄
梦安魂于九霄
火车驶向云外
但是以上通过时间来建立等待机制,建立并发 效率不高,不建议
通道
通道实现了在两个或多个Goroutine之间传递消息,通过通信的方式来共享内存
通道是类型相关的一个通道只能传递一种类型的值,该类型需要在声明时就指出
/*生产消费模型*/
func p(data chan int) {//参数int型的数据通道
for i := 0; i < 4; i++ {
fmt.Println("product data:", i)
data <- i//通过循环向通道中写入数据
}
close(data)//关闭通道,写完就关闭
}
func c(data chan int, done chan bool) {//参数添加了一个新的bool类型的通道
for x := range data {
fmt.Println("accept data:", x)//将data通道中的数据输出
}
done <- true //向done通道中写入true
//一个生产消费过程结束
}
func main() {
dat := make(chan int)
stop := make(chan bool)//建立通道
go p(dat)
go c(dat, stop)
<-stop //读通道
}
product data: 0
product data: 1
accept data: 0
accept data: 1
product data: 2
product data: 3
accept data: 2
accept data: 3
运用并发机制来编写一个石头剪刀布 的小游戏
用 1,2,3代替 石头剪刀布
import (
"fmt"
"math/rand"
"time"
)
func main() {
done := make(chan bool)
gamer1 := make(chan int)
gamer2 := make(chan int)
go game(gamer1)
go game(gamer2)
go pk(gamer1, gamer2, done)
<-done
}
func game(gamer chan int) {
rand.Seed(time.Now().Unix())
gamer <- rand.Intn(3) + 1
}
func pk(one, two chan int, done chan bool) {
a := <-one
b := <-two
if a == b {
fmt.Println(a, "pk", b, "平手")
} else if a == 1 && b == 2 || a == 2 && b == 3 {
fmt.Println(a, "pk", b, "胜利")
} else {
fmt.Println(a, "pk", b, "失败")
}
done <- true
}
//以上的程序有问题,应该是以时间为种子的原因导致两人同时进行的时候随机数产生的差别不大