Go并发
1.WaitGroup等待当前运行的协程
package main
import (
"fmt"
"runtime"
"sync"
)
// Go语言的并发指的是能让某个函数独立于其他函数运行的能力
// Go的调度器是在操作系统之上的
//Go的并发同步模型来自一个叫做通信顺序进程(CSP)的东西
//同步和传递数据的关键数据类型是通道
func main() {
// 分配一个逻辑处理器给调度器使用
runtime.GOMAXPROCS(1)
//wg用来等待程序完成
//计数加2,表示要等待2个goroutine
var wg sync.WaitGroup
wg.Add(2)
fmt.Println("Start Goroutines")
//声明一个匿名函数,创建一个goroutine
go func() {
// 在函数退出时调用Done来同志main函数工作已经完成
defer wg.Done()
for count := 0; count < 3; count++ {
for char := 'a'; char < 'a'+26; char++ {
fmt.Printf("%c ", char)
}
}
}()
go func(){
defer wg.Done()
for count := 0; count < 3; count++ {
for char := 'A'; char < 'A'+26; char++ {
fmt.Printf("%c ", char)
}
}
}()
//等待goroutine结束
fmt.Println("Waiting To Finish")
wg.Wait()
fmt.Println("\nTerminating Program")
}
2.互斥锁
在对共享资源进行计算的时候使用
package main
import (
"fmt"
"runtime"
"sync"
)
var (
// counter是所有goroutines都要增加其值的变量
counter int
// wg用来等待程序结束
wg sync.WaitGroup
// mutex用来定义一段代码临界区
mutex sync.Mutex
)
func main() {
// 计数为2,表示要等待两个goroutines
wg.Add(2)
go incCounter(1)
go incCounter(2)
wg.Wait()
fmt.Printf("Final Counter: %d\n",counter)
}
func incCounter(id int){
defer wg.Done()
for count:=0;count<2;count++{
// 同一时刻只允许一个goroutine进入
// 这个是临界区
mutex.Lock()
{
//捕获counter的值
value:=counter
// 当前goroutines从线程退出,并放回到队列
runtime.Gosched()
//增加本地的value变量的值
value++
counter = value
}
mutex.Unlock()
//释放锁,允许其他正在等待的goroutine
//进入临界区
}
}
mutex.Lock(){}的花括号只是为了方便看,可以省略。
3.无缓冲通道的使用
package main
import (
"fmt"
"sync"
"time"
)
//var wg sync.WaitGroup
//
//func main() {
// // 创建一个无缓冲的通道
// baton := make(chan int)
//
// // 为最后一位跑步者将计数加1
// wg.Add(1)
// //第一位跑步者持有接力棒
// go Runner(baton)
// // 第一位选手接棒
// baton <- 1
// wg.Wait()
//
//}
//
//func Runner(baton chan int) {
// var newRunner int
// // 等待接力棒
// runner := <-baton
//
// // 开始绕着跑道跑步
// fmt.Printf("Runner %d Running With Baton\n", runner)
// if runner != 4 {
// newRunner = runner + 1
// fmt.Printf("Running %d To Rhe Line\n", newRunner)
// go Runner(baton)
// }
// time.Sleep(1000 * time.Millisecond)
// //比赛结束了么
// if runner == 4 {
// fmt.Printf("Runner %d Finished,Race Over\n", runner)
// defer wg.Done()
// return
// }
// fmt.Printf("Runner %d Exchange with Runner %d\n", runner, newRunner)
// baton <- newRunner
//}
var wg sync.WaitGroup
func main() {
//创建一个无缓冲的通道
baton:=make(chan int)
wg.Add(1)
go Runner(baton) //第一位跑步者持有接力棒
baton<-1 //开始比赛
wg.Wait() //等待比赛结束
}
func Runner(baton chan int ){
var newRunner int
runner:=<-baton
fmt.Printf("第 %d 位选手开始跑\n",runner)
if runner!=4{
newRunner = runner+1
fmt.Printf("第 %d 位选手准备\n",runner)
go Runner(baton)
}
time.Sleep(1000*time.Millisecond)
if runner==4{
fmt.Printf("第%d位选手到达终点,比赛结束")
wg.Done() //完成的时候调用
}
//交给下一位
baton<-newRunner
}
来源:Go in Action