Go 中的并发:从基础知识到高级概念

秋瑶君_1550

秋瑶君_1550

2024-10-07

777人浏览

转载

go 中的并发:从基础知识到高级概念

目录

  1. 并发简介
  2. 并发与并行
  3. go 例程:并发的构建块
  4. 通道:go 例程之间的通信
  5. select 语句:管理多个通道
  6. 同步原语
  7. 并发模式
  8. 上下文包:管理取消和 超时。
  9. 最佳实践和常见陷阱**

1.并发简介

并发是同时处理多个任务的能力。在 go 中,并发性是一等公民,内置于该语言的核心设计中。 go 的并发方法基于通信顺序进程(csp),该模型强调进程之间的通信而不是共享内存。

2.并发与并行:

go 例程支持并发,这是独立执行进程的组合。
如果系统有多个 cpu 核心并且 go 运行时安排 go 例程并行运行,则可能会发生并行(同时执行)。

3。 go 例程:
并发的构建块是 go 例程,是由 go 运行时管理的轻量级线程。它是与其他函数或方法同时运行的函数或方法。 go 例程是 go 并发模型的基础。

主要特征:

  • 轻量级:go 例程比操作系统线程轻得多。您可以轻松创建数千个 go 例程,而不会显着影响性能。
  • 由 go 运行时管理:go 调度程序处理可用操作系统线程之间的 go 例程分配。
  • 廉价创建:启动 go 例程就像在函数调用之前使用 go 关键字一样简单。
  • 堆栈大小:go 例程从一个小堆栈(大约 2kb)开始,可以根据需要增长和缩小。

创建 go 例程:
要启动 go 例程,只需使用 go 关键字,后跟函数调用:

go functionname()

或者使用匿名函数:

go func() {
    // function body
}()

go-routine 调度:

  • go 运行时使用 m:n 调度程序,其中 m 个 go 例程被调度到 n 个操作系统线程上。
  • 这个调度程序是非抢占式的,这意味着 go 例程在空闲或逻辑阻塞时会产生控制权。

通讯与同步:

  • goroutine 通常使用通道进行通信,遵循“不要通过共享内存进行通信;通过通信来共享内存”的原则。
  • 对于简单的同步,您可以使用像sync.waitgroup或sync.mutex这样的原语。

示例及说明:

package main

import (
    "fmt"
    "time"
)

func printnumbers() {
    for i := 1; i 



<p><strong>说明:</strong></p>

  • 我们定义了两个函数:printnumbers 和 printletters。
  • 在 main 中,我们使用 go 关键字将这些函数作为 goroutine 启动。
  • 然后 main 函数休眠 2 秒,让 goroutine 完成。
  • 如果没有 goroutine,这些函数将按顺序运行。对于 goroutine,它们是同时运行的。
  • 输出将显示数字和字母交错,演示并发执行。

goroutine 生命周期:

  • goroutine 在使用 go 关键字创建时启动。
  • 当其功能完成或程序退出时,它终止。
  • 如果管理不当,goroutines 可能会泄漏,因此确保它们可以退出非常重要。

最佳实践:

  • 不要在库中创建 goroutine;让调用者控制并发。
  • 创建无限数量的 goroutine 时要小心。
  • 使用通道或同步原语在 goroutine 之间进行协调。
  • 考虑使用工作池来有效管理多个 goroutine。

带有 go 例程解释的简单示例

package main

import (
    "fmt"
    "time"
)

// printnumbers is a function that prints numbers from 1 to 5
// it will be run as a goroutine
func printnumbers() {
    for i := 1; i 



<p><strong>4.频道:</strong></p>

<p>通道是 go 中的一项核心功能,它允许 go 例程相互通信并同步执行。它们为一个 go 例程提供了一种将数据发送到另一个 go 例程的方法。</p><div class="aritcle_card flexRow artxards">
											<div class="artcardd flexRow">
												<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill3172" title="Git Pushing"><img
														src="https://img.php.cn/upload/skill/000/000/081/178947187743024.jpg" alt="Git Pushing" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
												<div class="aritcle_card_info flexColumn">
													<a rel="nofollow" href="/xiazai/skill3172" title="Git Pushing" class="overflowclass">Git Pushing</a>
													<p class="overflowclass">使用约定式提交信息暂存、提交和推送git更改。当用户想要提交和推送更改、提到推送到远程、或要求保存并推送工作时触发。也适用于用户说“推送更改”、“提交并推送”、“推送这个”、“推送到github”或类似git工作流程请求时。</p>
												</div>
												<a rel="nofollow" href="/xiazai/skill3172" title="Git Pushing" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
												</a>
											</div>
										</div>

<p><strong>频道的目的</strong></p>

<p>go 中的通道有两个主要用途:<br>
a) 通信:它们允许 goroutine 相互发送和接收值。<br>
b) 同步:它们可用于跨 goroutine 同步执行。</p>

<p>创建:使用 make 函数创建通道:<br></p>

<pre class="brush:php;toolbar:false;">ch := make(chan int)  // unbuffered channel of integers

发送:使用

ch 



<p>接收:使用 
</p>

<pre class="brush:php;toolbar:false;">value := 



<p><strong>频道类型</strong></p>

<p>a) 无缓冲通道:</p>

  • 创建时没有容量: ch := make(chan int)
  • 发送块直到另一个 goroutine 接收到。
  • 接收会阻塞,直到另一个 goroutine 发送。
ch := make(chan int)
go func() {
    ch 



<p>b) 缓冲通道:</p>

  • 使用容量创建: ch := make(chan int, 3)
  • 当缓冲区已满时仅发送块。
  • 仅当缓冲区为空时才阻塞接收。
ch := make(chan int, 2)
ch 



<p><strong>频道方向</strong></p>

<p>通道可以是定向的或双向的:</p>

  • 双向:chan t
  • 仅发送:chan
  • 仅接收:

示例:

func send(ch chan



<p><strong>关闭频道</strong></p>

<p>可以关闭通道以表示不再发送任何值:<br></p>

<pre class="brush:php;toolbar:false;">close(ch)

从封闭通道接收:

如果通道为空,则返回通道类型的零值。
您可以使用二值接收来检查通道是否关闭:

value, ok := 



<p><strong>跨频道</strong></p>

<p>您可以使用 for range 循环从通道接收值,直到通道关闭:<br></p>

<pre class="brush:php;toolbar:false;">for value := range ch {
    fmt.Println(value)
}

嘿,感谢您坚持到最后!我感谢您成为有价值的读者和学习者。请在此处以及我的 linkedin 和 github 上关注我 .

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

git 操作系统

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

5684

49

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

2264

5

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

1552

13

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

4999

3

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.08.29

2585

6

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.29

3108

10

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.29

2185

10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

4427

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2048

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
vscode手册
vscode手册

共0课时 | 0人学习

Git 教程
Git 教程

共21课时 | 7.8万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.8万人学习