Go并发
2023-09-14 09:06:34 时间
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
相关文章
- Go Web -- 模板引擎
- go在并发情况下使用map
- 从零开始基于go-thrift创建一个RPC服务
- 理解Go协程与并发
- 《Go语言实战》摘录:7.2 并发模式 - pool
- 《Go语言实战》摘录:6.3 并发 - 竞争状态
- 《Go语言实战》摘录:7.1 并发模式 - runner
- [Go] 函数/方法 的 变参
- Go语言基础之并发
- [阅读笔记]Go语言并发之美
- 【Go语言】【8】GO语言的条件语句和选择语句
- go如何进行交叉编译
- 【Go课件】golang命令行应用脚手架工具:urfave cli入门示例
- [Go] flag package 指南: 命令行参数标记的解析
- [Go] Colly 使用 POST 提交 application/x-www-form-urlencoded 示范
- 【Go基础】使用go语言函数
- [手游项目3]-9-Go语言sync.Map(在并发环境中使用的map)
- Go语言并发与并行学习笔记(二)
- Go语言自学系列 | golang并发编程之原子操作详解
- Go语言自学系列 | golang并发编程之Timer
- Go语言自学系列 | golang并发编程之select switch
- Go语言自学系列 | golang并发编程之Mutex互斥锁实现同步
- Go语言自学系列 | golang并发编程之runtime包
- 387集Go语言核心编程培训视频教材整理 | 面向对象编程(六)
- go-rabbitmq
- go正则贴吧
- go 继承
- Linux下安装Go环境
- Go协程、并发、信道