4-golang协程(goroutine)和管道(channel)

2024-08-28 02:32

本文主要是介绍4-golang协程(goroutine)和管道(channel),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

4-golang协程(goroutine)和管道(channel)

1. 并发和并行

多线程程序在单核上运行,就是并发

多线程程序在多核上运行,就是并行

2. go协程和线程

  • Go主线程(也可以称为线程,可以理解为进程):一个Go线程上可以起多个协程,协程是轻量级的线程
  • Go协程的特点
    • 有独立的栈空间
    • 共享程序堆空间
    • 调度由用户控制
    • 协程是轻量级的线程
func test() {for i := 0; i < 10; i++ {fmt.Println("test() hello world " + strconv.Itoa(i))time.Sleep(time.Second)}
}func main() {go test() // 开启了一个协程for i := 0; i < 10; i++ {fmt.Println("main() hello golang " + strconv.Itoa(i))time.Sleep(time.Second)}
}
  • 如果主线程退出了,则协程及时还没有执行完毕,也会退出
  • 写成也可以在主线程没有退出前就自己结束了,比如完成了自己的任务

3. goroutine的调度模型–MPG模式

M:操作系统的主线程(是物理线程)

P:协程执行需要的上下文

G:协程

4. 管道(Channel)

  • channel是一个数据结构,遵循先进先出
  • 多goroutine访问时,不需要加锁,channel是线程安全的
  • 一个channel中的数据,数据类型要一致。(一个string的channel,只能存放string数据类型)
  • channel需要make后使用,make时需要设置channel长度
  • channel数据放满后,再放数据会报错,取出数据后,可以再放数据
  • 在没有协程的情况下,channel数据取完后,再取数据会报错
  • 使用内置的 close(channelName) 可以关闭channel,此时不能再向channel写数据,但是可以读数据
  • 遍历channel使用for-range遍历。在遍历时,如果channel没有关闭,则会报错;如果channel已经关闭,会再遍历完成后退出遍历。(遍历不要使用普通for,因为在取出channel数据后,channel长度会改变)
package mainimport "fmt"// write data
func writeData(intChan chan int) {for i := 1; i <= 1000; i++ {// 放入数据intChan <- ifmt.Printf("writeData 写入数据=%v\n", i)}// 写完后关闭close(intChan)
}func readChain(intChan chan int, exitChan chan bool) {for {v, ok := <-intChanif !ok {break}fmt.Printf("readData 读到数据=%v\n", v)}// 读完数据后,任务完成exitChan <- trueclose(exitChan)
}func main() {// 创建两个管道intChan := make(chan int, 1000)exitChan := make(chan bool, 1)go writeData(intChan)go readChain(intChan, exitChan)for {_, ok := <-exitChanif !ok {break}}}

这篇关于4-golang协程(goroutine)和管道(channel)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1113475

相关文章

使用协程实现高并发的I/O处理

文章目录 1. 协程简介1.1 什么是协程?1.2 协程的特点1.3 Python 中的协程 2. 协程的基本概念2.1 事件循环2.2 协程函数2.3 Future 对象 3. 使用协程实现高并发的 I/O 处理3.1 网络请求3.2 文件读写 4. 实际应用场景4.1 网络爬虫4.2 文件处理 5. 性能分析5.1 上下文切换开销5.2 I/O 等待时间 6. 最佳实践6.1 使用 as

Go Channel的实现

channel作为goroutine间通信和同步的重要途径,是Go runtime层实现CSP并发模型重要的成员。在不理解底层实现时,经常在使用中对channe相关语法的表现感到疑惑,尤其是select case的行为。因此在了解channel的应用前先看一眼channel的实现。 Channel内存布局 channel是go的内置类型,它可以被存储到变量中,可以作为函数的参数或返回值,它在r

Golang进程权限调度包runtime

关于 runtime 包几个方法: Gosched:让当前线程让出 cpu 以让其它线程运行,它不会挂起当前线程,因此当前线程未来会继续执行GOMAXPROCS:设置最大的可同时使用的 CPU 核数Goexit:退出当前 goroutine(但是defer语句会照常执行)NumGoroutine:返回正在执行和排队的任务总数GOOS:目标操作系统NumCPU:返回当前系统的 CPU 核数量 p

Golang 网络爬虫框架gocolly/colly(五)

gcocolly+goquery可以非常好地抓取HTML页面中的数据,但碰到页面是由Javascript动态生成时,用goquery就显得捉襟见肘了。解决方法有很多种: 一,最笨拙但有效的方法是字符串处理,go语言string底层对应字节数组,复制任何长度的字符串的开销都很低廉,搜索性能比较高; 二,利用正则表达式,要提取的数据往往有明显的特征,所以正则表达式写起来比较简单,不必非常严谨; 三,使

Golang网络爬虫框架gocolly/colly(四)

爬虫靠演技,表演得越像浏览器,抓取数据越容易,这是我多年爬虫经验的感悟。回顾下个人的爬虫经历,共分三个阶段:第一阶段,09年左右开始接触爬虫,那时由于项目需要,要访问各大国际社交网站,Facebook,myspace,filcker,youtube等等,国际上叫得上名字的社交网站都爬过,大部分网站提供restful api,有些功能没有api,就只能用http抓包工具分析协议,自己爬;国内的优酷、

Golang网络爬虫框架gocolly/colly(三)

熟悉了《Golang 网络爬虫框架gocolly/colly 一》和《Golang 网络爬虫框架gocolly/colly 二》之后就可以在网络上爬取大部分数据了。本文接下来将爬取中证指数有限公司提供的行业市盈率。(http://www.csindex.com.cn/zh-CN/downloads/industry-price-earnings-ratio) 定义数据结构体: type Zhj

Golang支持平滑升级的HTTP服务

前段时间用Golang在做一个HTTP的接口,因编译型语言的特性,修改了代码需要重新编译可执行文件,关闭正在运行的老程序,并启动新程序。对于访问量较大的面向用户的产品,关闭、重启的过程中势必会出现无法访问的情况,从而影响用户体验。 使用Golang的系统包开发HTTP服务,是无法支持平滑升级(优雅重启)的,本文将探讨如何解决该问题。 一、平滑升级(优雅重启)的一般思路 一般情况下,要实现平滑

Golang服务平滑重启

与重载配置相同的是我们也需要通过信号来通知server重启,但关键在于平滑重启,如果只是简单的重启,只需要kill掉,然后再拉起即可。平滑重启意味着server升级的时候可以不用停止业务。 我们先来看下Github上有没有相应的库解决这个问题,然后找到了如下三个库: facebookgo/grace - Graceful restart & zero downtime deploy for G

Golang test编译使用

创建文件my_test.go package testsimport "testing"func TestMy(t *testing.T) {t.Log("TestMy")} 通常用法: $ go test -v -run TestMy my_test.go=== RUN TestMyTestMy: my_test.go:6: TestMy--- PASS: TestMy (0.

Golang GUI入门——andlabs ui

官方不提供gui标准库,只好寻求第三方库。 https://github.com/google/gxui 这个gui库是谷歌内部人员提供的,并不是谷歌官方出品,现在停止维护,只好作罢。 第三方gui库 找了好多,也比较了好多,最终决定使用的是还是 https://github.com/andlabs/ui 相信golang gui还会发展的更好,期待更优秀的gui库 由于andlabs