脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - GO语言协程创建使用并通过channel解决资源竞争

GO语言协程创建使用并通过channel解决资源竞争

2022-09-15 16:30Jeff的技术栈 Golang

这篇文章主要为大家介绍了GO语言协程创建使用并通过channel解决资源竞争,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪

创建协程

goroutine是go的设计核心,就是协程
主协程终止了,子协程也终止

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
import (
    "fmt"
    "time"
)
func newTask() {
    for {
        fmt.Println("this is a newTask")
        time.Sleep(time.Second) //延时1s
    }
}
func main() {
    go newTask() //新建一个协程, 新建一个任务
    for {
        fmt.Println("this is a main goroutine")
        time.Sleep(time.Second) //延时1s
    }
}

 

主协程终止,子协程也终止

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
import (
    "fmt"
    "time"
)
//主协程退出了,其它子协程也要跟着退出
func main() {
    go func() {
        i := 0
        for {
            i++
            fmt.Println("子协程 i = ", i)
            time.Sleep(time.Second)
        }
    }() //别忘了()
    i := 0
    for {
        i++
        fmt.Println("main i = ", i)
        time.Sleep(time.Second)
        if i == 2 {
            break
        }
    }
}

 

runtime包

 

Gosched让出CPU时间片

等待其他协程执行完

runtime.Gosched()用于让出CPU时间片,让出当前goroutine(协程)的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢复执行。
类似:接力赛,A跑了一会碰到代码runtime.Gosched()就把接力棒交给B,A歇着,B继续跑

案例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
import (
    "fmt"
    "runtime"
)
func main() {
    go func() {
        for i := 0; i < 5; i++ {
            fmt.Println("go")
        }
    }()
    for i := 0; i < 2; i++ {
        //让出时间片,先让别的协议执行,它执行完,再回来执行此协程
        runtime.Gosched()
        fmt.Println("hello")
    }
}
 
 
go
go
go
go
go
hello
hello

 

Goexit立即结束当前协程

?
1
runtime.Goexit()  //立即结束当前协程

案例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
import (
    "fmt"
    "runtime"
)
func test() {
    defer fmt.Println("ccccccccccccc")
    //return //终止此函数
    runtime.Goexit() //终止所在的协程
    fmt.Println("dddddddddddddddddddddd")
}
func main() {
    //创建新建的协程
    go func() {
        fmt.Println("aaaaaaaaaaaaaaaaaa")
 
        //调用了别的函数
        test()
        fmt.Println("bbbbbbbbbbbbbbbbbbb")
    }() //别忘了()
    //特地写一个死循环,目的不让主协程结束
    for {
    }
}
aaaaaaaaaaaaaaaaaa
ccccccccccccc

 

GOMAXPROCS设置并行CPU核数最大值,并返回之前的值

?
1
runtime.GOMAXPROCS() //设置并行CPU核数最大值,并返回之前的值
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import (
    "fmt"
    "runtime"
)
func main() {
    //n := runtime.GOMAXPROCS(1) //指定以1核运算
    n := runtime.GOMAXPROCS(2) //指定以8核运算
    fmt.Println("n = ", n)
    for {
        go fmt.Print(1)
        fmt.Print(0)
    }
}

 

runtime.NumGoroutine()获取当前运行中的goroutine数量

先介绍一个最简单的监控方式。

通过 runtime.NumGoroutine() 获取当前运行中的 goroutine 数量,通过它确认是否发生泄漏。

?
1
2
3
4
5
6
7
8
9
10
func main() {
 go test()
 go test()
 go test()
 go test()
 a:=runtime.NumGoroutine()
 fmt.Println(a) // 5
 for  {
 }
}

 

多任务资源竞争问题

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main
import (
    "fmt"
    "time"
)
//定义一个打印机,参数为字符串,按每个字符打印
//打印机属于公共资源
func Printer(str string) {
    for _, data := range str {
        fmt.Printf("%c", data)
        time.Sleep(time.Second)
    }
    fmt.Printf(" ")
}
func person1() {
    Printer("hello")
}
func person2() {
    Printer("world")
}
func main() {
    //新建2个协程,代表2个人,2个人同时使用打印机
    go person1()
    go person2()
    //特地不让主协程结束,死循环
    for {
    }
}

 

通过channel解决资源竞争问题

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main
import (
    "fmt"
    "time"
)
//全局变量,创建一个channel
var ch = make(chan int)
//定义一个打印机,参数为字符串,按每个字符打印
//打印机属于公共资源
func Printer(str string) {
    for _, data := range str {
        fmt.Printf("%c", data)
        time.Sleep(time.Second)
    }
    fmt.Printf(" ")
}
//person1执行完后,才能到person2执行
func person1() {
    Printer("hello")
    ch <- 666 //给管道写数据,发送
}
func person2() {
    <-ch //从管道取数据,接收,如果通道没有数据他就会阻塞
    Printer("world")
}
func main() {
    //新建2个协程,代表2个人,2个人同时使用打印机
    go person1()
    go person2()
    //特地不让主协程结束,死循环
    for {
    }
}

 

主协程如何等其余协程完再退出

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var wg sync.WaitGroup
wg.Add(2//任务数
wg.Done() //结束
wg.Wait() //等待
package main
import (
    "fmt"
    "sync"
)
var wg sync.WaitGroup
func main() {
    wg.Add(2)
    out := producer()
    consumer(out)
    defer fmt.Println("主线程结束")
    wg.Wait()  //等待
}
//此通道只能写,不能读
func producer() chan interface{} {
    ch := make(chan interface{})
    go func() {
        for i := 0; i < 5; i++ {
            ch <- fmt.Sprintf("协程1-%d", i) //写入字符串
        }
        defer close(ch)
        wg.Done()  //结束
    }()
    return ch
}
//此channel只能读,不能写
func consumer(data chan interface{}) {
    defer fmt.Println("读取结束")
    go func() {
        for num := range data {
            fmt.Println(num)
        }
        wg.Done() //结束
    }()
}

以上就是GO语言协程创建使用并通过channel解决资源竞争的详细内容,更多关于GO语言协程channel解决资源竞争的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/guyouyin123/p/13985447.html

延伸 · 阅读

精彩推荐
  • Golanggolang中snappy的使用场合实例详解

    golang中snappy的使用场合实例详解

    在java 和go语言 大字符传达的时候, 采用snappy 压缩 解压缩是最好的方案。下面这篇文章主要给大家介绍了关于golang中snappy使用场合的相关资料,文中通过...

    daisy2052020-05-12
  • Golanggo语言实现抓取高清图片

    go语言实现抓取高清图片

    本文给大家分享的是使用go语言实现的抓取高清美女图片的代码,原理非常简单,这里就不多废话了,主要是看到很多小伙伴使用python实现的,心血来潮就...

    脚本之家4772020-04-24
  • GolangGo语言带缓冲的通道实现

    Go语言带缓冲的通道实现

    这篇文章主要介绍了Go语言带缓冲的通道实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随...

    zx7342021-06-01
  • GolangGo 代码生成工具详解

    Go 代码生成工具详解

    这篇文章主要介绍了Go 代码生成工具详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    新亮笔记4912021-04-18
  • Golang盘点Golang中非常好用的几个包

    盘点Golang中非常好用的几个包

    Go Kit本身不是一个框架,而是一套微服务工具集, 它可以用来解决分布式系统开发中的大多数常见问题. 所以你可以专注于你的业务逻辑中。...

    梦回故里归来6672021-08-30
  • Golang如何在VScode 中编译多个Go文件

    如何在VScode 中编译多个Go文件

    这篇文章主要介绍了VScode 中编译多个Go文件的实现方法,本文通过实例图文并茂的形式给大家介绍的非常详细,需要的朋友可以参考下...

    叨陪鲤56922021-09-17
  • Golanggo1.8之安装配置具体步骤

    go1.8之安装配置具体步骤

    下面小编就为大家带来一篇go1.8之安装配置具体步骤。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 ...

    jingxian5542020-05-07
  • GolangGo语言中通过Lua脚本操作Redis的方法

    Go语言中通过Lua脚本操作Redis的方法

    这篇文章主要给大家介绍了关于Go语言中通过Lua脚本操作Redis的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    吃土的汉子3742020-05-13