Go 语言支持并发,我们只需要通过 go 关键字来开启 goroutine 即可。

一、goruntine

goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。

goroutine 语法格式:

go 函数名( 参数列表 )

例如:

go f(x, y, z)

开启一个新的 goroutine:

f(x, y, z)

Go 允许使用 go 语句开启一个新的运行期线程, 即 goroutine,以一个不同的、新创建的 goroutine 来执行一个函数。

同一个程序中的所有 goroutine 共享同一个地址空间。

实例

package mainimport ("fmt""time"
)func say(s string) {for i := 0; i < 5; i++ {time.Sleep(100 * time.Millisecond)fmt.Println(s)}
}func main() {// 让另外一个线程运行go say("world")// 当前线程继续运行say("hello")
}

执行以上代码,你会看到输出的 hello 和 world 是没有固定先后顺序。

因为它们是两个 goroutine 在执行:

world
hello
hello
world
world
hello
hello
world
world
hello

二、通道(channel)

通道(channel)是用来传递数据的一个数据结构。

通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。

操作符 <- 用于指定通道的方向,发送或接收。

如果未指定方向,则为双向通道。

ch <- v    // 把 v 发送到通道 ch
v := <-ch  // 从 ch 接收数据// 并把值赋给 v

声明一个通道很简单,我们使用chan关键字即可,

通道在使用前必须先创建:

ch := make(chan int)

注意:默认情况下,通道是不带缓冲区的。发送端发送数据,同时必须有接收端相应的接收数据。

实例

以下实例通过两个 goroutine 来计算数字之和,

在 goroutine 完成计算后,它会计算两个结果的和:

package mainimport "fmt"func sum(s []int, c chan int) {sum := 0for _, v := range s {sum += v}c <- sum // 把 sum 发送到通道 c
}func main() {s := []int{7, 2, 8, -9, 4, 0}c := make(chan int)// 后一半数组go sum(s[:len(s)/2], c)// 前一半数组go sum(s[len(s)/2:], c)x, y := <-c, <-c // 从通道 c 中接收fmt.Println(x, y, x+y)
}

输出结果为:

-5 17 12

三、通道缓冲区

通道可以设置缓冲区,通过 make 的第二个参数指定缓冲区大小:

ch := make(chan int, 100)

带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放在缓冲区里面,可以等待接收端去获取数据,而不是立刻需要接收端去获取数据。

不过由于缓冲区的大小是有限的,所以还是必须有接收端来接收数据的,否则缓冲区一满,数据发送端就无法再发送数据了。

注意:如果通道不带缓冲,发送方会阻塞直到接收方从通道中接收了值。

如果通道带缓冲,发送方则会阻塞直到发送的值被拷贝到缓冲区内;

如果缓冲区已满,则意味着需要等待直到某个接收方获取到一个值。

接收方在有值可以接收之前会一直阻塞。

实例

package mainimport "fmt"func main() {// 这里我们定义了一个可以存储整数类型的带缓冲通道// 缓冲区大小为2ch := make(chan int, 2)// 因为 ch 是带缓冲的通道,我们可以同时发送两个数据// 而不用立刻需要去同步读取数据ch <- 1ch <- 2// 获取这两个数据fmt.Println(<-ch)fmt.Println(<-ch)
}

执行输出结果为:

1
2

四、Go 遍历通道与关闭通道

Go 通过 range 关键字来实现遍历读取到的数据,类似于与数组或切片。格式如下:

v, ok := <-ch

如果通道接收不到数据后 ok 就为 false,这时通道就可以使用 close() 函数来关闭。

实例

package mainimport ("fmt"
)func fibonacci(n int, c chan int) {x, y := 0, 1for i := 0; i < n; i++ {c <- xx, y = y, x+y}close(c)
}func main() {c := make(chan int, 10)go fibonacci(cap(c), c)// range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个// 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据// 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不// 会结束,从而在接收第 11 个数据的时候就阻塞了。for i := range c {fmt.Println(i)}
}

执行输出结果为:

0
1
1
2
3
5
8
13
21
34

https://www.runoob.com/go/go-concurrent.html

Go 并发 多线程 goroutine channel 实例相关推荐

  1. golang并发编程goroutine+channel(一)

    go语言的设计初衷除了在不影响程序性能的情况下减少复杂度,另一个目的是在当今互联网大量运算下,如何让程序的并发性能和代码可读性达到极致.go语言的并发关键词 "go" go dos ...

  2. Golang并发——并发技术Goroutine和channel的使用、定时器、生产者消费者、条件变量、select

    Goroutine: goroutine是Go并行设计的核心.goroutine说到底其实就是协程,它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些gor ...

  3. java中thread实例_Java多线程并发执行demo代码实例

    主类:MultiThread,执行并发类 package java8test; import java.util.ArrayList; import java.util.List; import ja ...

  4. Java 并发/多线程教程(四)-并发模型

    本系列译自jakob jenkov的Java并发多线程教程(本章节部分内容参考http://ifeve.com/并发编程模型),个人觉得很有收获.由于个人水平有限,不对之处还望矫正! 并发系统可以有多 ...

  5. Java 并发/多线程教程(五)-相同线程

    本系列译自jakob jenkov的Java并发多线程教程,个人觉得很有收获.由于个人水平有限,不对之处还望矫正! 相同线程是一并发框架模型,是一个单线程系统向外扩展成多个单线程的系统.这样的结果就是 ...

  6. golang中并发sync和channel

    golang中并发sync和channel chenbaoke · 2014-12-08 13:00:01 · 19151 次点击 · 预计阅读时间 5 分钟 · 不到1分钟之前 开始浏览 这是一个创 ...

  7. goroutine, channel 和 CSP

    2019独角兽企业重金招聘Python工程师标准>>> 引子 老听 clojure 社区的人提起 core.async ,说它如何好用,如何简化了并发编程的模型,不由得勾起了我的好奇 ...

  8. java并发多线程面试_Java多线程并发面试问答

    java并发多线程面试 Today we will go through Java Multithreading Interview Questions and Answers. We will al ...

  9. Java并发工具辅助类代码实例

    java中的并发工具类 一:等待多线程完成的CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作. packag``.fuzhulei; import ja ...

  10. 推测的删除锁(Speculative Lock Elision):实现高并发多线程执行

    背景 SLE全称Speculative Lock Elision,我称之为推测的删除锁.这是一篇关于SLE的论文翻译,但是因为本人英语功底很差,所以翻译的不通顺而且会有很多错误的地方.之所以把它发出来 ...

最新文章

  1. 2022-2028年中国HDPE膜行业市场研究及投资发展分析报告
  2. java arraylist 源代码_Java中ArrayList源码浅析
  3. 在C#中使用gRPC及protobuf简介
  4. 数据结构与算法 - 稀疏数组(理解+代码实现案例)
  5. 数据结构与算法-复杂的问题简单化
  6. mongodb 持久化 mysql_最详细的python爬虫指南(四):持久化操作(mongoDB、mysql)...
  7. c语言 程序结集,c语言(结体程序设计).doc
  8. Asp.net中Mysql存储中文乱码解决方法
  9. Ubuntu-解决包依赖关系的三种办法
  10. 基于IC设计的实用ISP算法介绍
  11. 使用 MTR 分析网络延迟及丢包
  12. 【CSAPP】二进制拆弹实验
  13. 【爬虫+数据可视化】Python爬取CSDN博客访问量数据并绘制成柱状图
  14. IMU预积分的简单理解
  15. 如何去掉XP系统中文件夹的只读属性
  16. 【Tensorflow教程笔记】常用模块 tf.function :图执行模式
  17. 三星a5100多少钱_请问三星A5100现在啥价格?
  18. 【docker】Docker核心技术快速入门及私有仓库搭建
  19. vue 后台翻译_前端使用vue-i18n做中英文翻译
  20. 网络图片转换为文件类型(File)

热门文章

  1. 空气污染指数的计算公式是什么?(API)
  2. 微信小游戏排行榜设计技术梳理
  3. 《Visual C# 从零开始学》
  4. bash实现自动补全
  5. 如何理解base href=%=basePath%
  6. Gradle Maven部署,转化
  7. 子模的性质(submodular)
  8. 拓端tecdat|Python银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机svm分析营销活动数据
  9. 拓端tecdat|视频:R语言中的时间序列分析模型:ARIMA-ARCH / GARCH模型分析股票价格
  10. python定义一维数组