前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go语言并发之并发实现、多核CPU设置、多协程间的通信、select、多协程间的同步(二十一)

Go语言并发之并发实现、多核CPU设置、多协程间的通信、select、多协程间的同步(二十一)

作者头像
友儿
发布2022-09-11 14:08:29
9820
发布2022-09-11 14:08:29
举报
文章被收录于专栏:友儿

Go语言并发之并发实现、多核CPU设置、多协程间的通信、select、多协程间的同步 目录结构

代码语言:javascript
复制
├── gorotine
│    └── gorotine.go
└── main.go

  • 并发实现:协程
    • 启动协程(加go关键字)

gorotine.go文件

代码语言:javascript
复制
     package gorotine
     import (
         "fmt"
         "time"
     )
     func Loop()  {
         for i:=1;i<11;i++ {
             //防止程序运行太快,看不到是否为并发执行,这里暂停10微秒
             time.Sleep(time.Microsecond * 10)
             fmt.Printf("%d,",i)
         }
     }   

main.go文件

代码语言:javascript
复制
    package main
    import (
        "./gorotine"
        "time"
    )
    func main() {
        //调用2次,串行执行
        //gorotine.Loop()
        //gorotine.Loop()
        //运行结果:1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,
    
        //并发,并发执行
        go gorotine.Loop()
        go gorotine.Loop()
        //防止并发运行速度过快,还未在终端输出程序已经结束,这样看不到结果,所以暂停了5秒钟
        time.Sleep(time.Second * 5)
        //运行结果:1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,
    }
  • 多核CPU设置
代码语言:javascript
复制
    package main
    import (
        "./gorotine"
        "fmt"
        "runtime"
        "time"
    )
    func main() {
        //调用2次,串行执行
        //gorotine.Loop()
        //gorotine.Loop()
        //运行结果:1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,
    
        //并发,并发执行
        fmt.Printf("cup num = %d", runtime.NumCPU())  // cup num = 12
        fmt.Print("\n")
        runtime.GOMAXPROCS(runtime.NumCPU() - 1)   //限制go程序的运行核心数,一般总核心数减一
        go gorotine.Loop()  // 加go关键字即可实现协程
        go gorotine.Loop()
        //防止并发运行速度过快,还未在终端输出程序已经结束,这样看不到结果,所以暂停了5秒钟
        time.Sleep(time.Second * 5)
        //运行结果:1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,
    }
  • 多协程间的通信
    • channel(管道)

gorotine.go文件

代码语言:javascript
复制
    package gorotine
    
    import (
        "fmt"
        "time"
    )
    var chanInt chan int = make(chan int, 10) //创建缓存为10的管道
    
    func Send()  {//向管道发送数据
        time.Sleep(time.Second * 1)
        chanInt <- 1
        time.Sleep(time.Second * 1)
        chanInt <- 2
        time.Sleep(time.Second * 1)
        chanInt <- 3
    }
    
    func Receive()  {//获取管道数据
        num := <- chanInt
        fmt.Println("num:", num)
        fmt.Print("\n")
        num = <- chanInt
        fmt.Println("num:", num)
        fmt.Print("\n")
        num = <- chanInt
        fmt.Println("num:", num)
    }

main.go文件

代码语言:javascript
复制
    package main
    
    import (
        "./gorotine"
        "time"
    )
    
    func main() {
        go gorotine.Send()     //启动发送数据的协程
        go gorotine.Receive()  //启动接收数据的协程
        //防止并发运行速度过快,还未在终端输出程序已经结束,这样看不到结果,所以暂停了5秒钟
        time.Sleep(time.Second * 5)
        //结果:
        /*
        num: 1
        num: 2
        num: 3
        */
    }
  • select

gorotine.go文件

代码语言:javascript
复制
    package gorotine
    
    import (
        "fmt"
        "time"
    )
    var chanInt chan int = make(chan int, 10) //创建缓存为10的管道
    var timeout chan bool = make(chan bool) //创建管道
    
    func Send()  {//向管道发送数据
        time.Sleep(time.Second * 1)
        chanInt <- 1
        time.Sleep(time.Second * 1)
        chanInt <- 2
        time.Sleep(time.Second * 1)
        chanInt <- 3
        time.Sleep(time.Second * 2)
        timeout <- true
    }
    
    func Receive()  {//获取管道数据,同时读取两个文件
        for  {
            select {
            case num:=<-chanInt:
                fmt.Println("num:", num)
            case <-timeout:
                 fmt.Println("timeout...")
            }
        }
        //应用场景:十个协程读10个不同文件数据往一个协程向文件写数据
    }

main.go文件

代码语言:javascript
复制
    package main
    
    import (
        "./gorotine"
        "time"
    )
    
    func main() {
        go gorotine.Send()     //启动发送数据的协程
        go gorotine.Receive()  //启动接收数据的协程
        //防止并发运行速度过快,还未在终端输出程序已经结束,这样看不到结果,所以暂停了5秒钟
        time.Sleep(time.Second * 5)
        //结果:
        /*
        num: 1
        num: 2
        num: 3
        timeout...
        */
    }
  • 多协程间的同步(多个协程读取不同文件,写文件的协程把读出来的数据完成后再进行别的操作)
    • 系统工具sync.waitgroup
      • Add(delta int ) 添加携程记录
      • Done() 移除协程记录
      • Wait() 同步等待所有记录的协程全部结束

gorotine.go文件

代码语言:javascript
复制
    package gorotine
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    var WG sync.WaitGroup
    //读取数据
    func Read()  {
        for i:=0;i<3;i++ {
            WG.Add(1)   //添加携程记录
        }
    }
    //写入数据
    func Write()  {
        for i:=0;i<3;i++ {
            time.Sleep(time.Second * 2)
            fmt.Println("Done ->", i)
            WG.Done()      //移除协程记录
        }
    }

main.go文件

代码语言:javascript
复制
    package main
    
    import (
        "fmt"
        "time"
        "./gorotine"
    )
    
    func main() {
        gorotine.Read()
        go gorotine.Write()
        gorotine.WG.Wait()
        fmt.Println(" All done!")
        //结果:
        /*
        Done -> 0
        Done -> 1
        Done -> 2
        All done!
        */
    
        time.Sleep(time.Second * 5)
    }

下面是拓展(对上面的代码合并一下):

代码语言:javascript
复制
    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    var wg sync.WaitGroup
    
    var arr = []int{1,2,3}
    
    func main() {
        for _,val:=range arr{
            wg.Add(1) //添加携程记录
            go func(val int) {
                time.Sleep(time.Second * 10)
                fmt.Println("Done ->", val)//执行后续程
                defer wg.Done()
            }(val)
        }
        wg.Wait() //移除协程记录
        fmt.Println(" All done!")  //执行后续程序
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档