我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

创建协程

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

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
	}
}

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

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继续跑

案例:

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立即结束当前协程

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

案例:

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核数最大值,并返回之前的值

runtime.GOMAXPROCS() //设置并行CPU核数最大值,并返回之前的值
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 数量,通过它确认是否发生泄漏。

func main() {
 go test()
 go test()
 go test()
 go test()
 a:=runtime.NumGoroutine()
 fmt.Println(a) // 5
 for  {
 }
}

多任务资源竞争问题

package main
import (
	"fmt"
	"time"
)
//定义一个打印机,参数为字符串,按每个字符打印
//打印机属于公共资源
func Printer(str string) {
	for _, data := range str {
		fmt.Printf("%c", data)
		time.Sleep(time.Second)
	}
	fmt.Printf("\n")
}
func person1() {
	Printer("hello")
}
func person2() {
	Printer("world")
}
func main() {
	//新建2个协程,代表2个人,2个人同时使用打印机
	go person1()
	go person2()
	//特地不让主协程结束,死循环
	for {
	}
}

通过channel解决资源竞争问题

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("\n")
}
//person1执行完后,才能到person2执行
func person1() {
	Printer("hello")
	ch <- 666 //给管道写数据,发送
}
func person2() {
	<-ch //从管道取数据,接收,如果通道没有数据他就会阻塞
	Printer("world")
}
func main() {
	//新建2个协程,代表2个人,2个人同时使用打印机
	go person1()
	go person2()
	//特地不让主协程结束,死循环
	for {
	}
}

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

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解决资源竞争的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录