后端实践--go并发编程 青训营

简介: 后端实践--go并发编程 青训营

后端实践--go并发编程 青训营

go的擅长领域就是高并发编程!!由于go语言的出现时间较晚,已经是并发编程较为普及的时代,所以go 语言在设计的时候就天生支持并发。

先了解一下并发和并行的概念。并发是指在一个时间段内多个任务共同推进,如核心上跑多个任务,一般会由于时间片轮转调度这多个任务在一个时间段内看上去同时在推进;而并行是指安排多个核心,每个核心去执行者多个任务中的一个或多个。

go 通过goroutine 实现并发。goroutine类似于线程,属于==用户态的线程==,比内核态的线程更轻量。goroutinego 运行时调度完成的,而内核态线程是由OS调度的。

一般goroutine 配合函数使用。相当于启动一个新的线程去执行这个函数。

channel: 在多个goroutine通信

1. goroutine

func hello(){
  fmt.Println("aaaa")
}
// 这里会创建一个主goroutine
// 主goroutine退出了,那么其他从属的goroutine也就退出了
func main(){
  // 启动一个新的goroutine(线程)执行这个函数
  go hello()
  // 主执行流正常往下执行
  fmt.Println("bbb")
  tmie.Sleep(time.Second)
}

等待goroutine 结束 (有点像信号量)

// 声明全局等待组变量
var wg sync.WaitGroup
func hello() {
  defer wg.Done() // 告知当前goroutine完成   -- 操作
  fmt.Println("hello")  
}
func main() {
  wg.Add(1) // 登记1个goroutine             ++操作
  go hello()
  fmt.Println("你好")
  wg.Wait() // 阻塞等待登记的goroutine完成    等到wg减到0
}

goroutine调度 --- GMP调度系统

G: goroutine 每执行一次go f()就创建一个 G,包含要执行的函数和上下文信息。

M: Machine 实际干活的。和内核线程是一一映射的关系。

P 管理者,管理goroutine。管理 goroutine 执行所需的资源,最多有 GOMAXPROCS 个。

GOMAXPROCS

// 设置执行当前任务的CPU核心数,默认是所有的核心
runtime.GOMAXPROCS(4)
runtime.NumCPU()

goroutineOS线程的区别

  1. 一个os线程可以对应多个goroutine
  2. go程序也可以同时使用多个os 线程
  3. 他们是多对多的关系

2. channel

就可以理解为一个类型。--- 引用类型!

三个常用的引用类型:切片、mapchan ==需要make 初始化。==

实现多 goroutine间通信。

有点像管道通信,遵循先入先出原则。

声明通道但没有初始化时其为nil,这时读取和写入都会都会阻塞。

自带访问控制机制:==通道开启时==,当通道为空时取值会阻塞住;当通道为满时写入也会阻塞住。通道关闭且有缓冲区时:不能写入,但是可以读取值直到读完。

// 声明一个channel管道,只能存放int类型的变量
var a chan int
var b chan []string
...
// 初始化(不带缓冲区)
a = make(chan int)
// 初始化(带缓冲区),代缓冲区的通道可以把接收的的数据先存到通道里
b = make(chan []string, 16)

chan 操作 <-

向通道里写:a <- 1

从通道里读:ch := <- a

关闭通道:close(a) , 这个别忘了!

// 循环取值
a := make(chan int, 10)
// 一样的:
// 若通道是开启的没有close,那么这里取完值后会阻塞!!!
// 只有通道关闭时取完值后会返回退出循环
for i := range a{
  // ...
}
// 手动判断停止
for{
  // 若通道是开启的没有close,那么这里取完值后会阻塞!!!
  // 只有通道关闭时取完值后会返回:对应类型的零值和 false
  x,ok := <- a
  if !ok{
    // 读完了
    break
  }
  // ...
}

确保只执行一次。

var once sync.Once
// ...
// 确保只关闭一次,关闭已经关闭了的chan会引发panic!!
once.Do(func(){ close(a) })

单向通道

通常用于函数参数,限制为只允许读取或只允许写入的通道。

// 只能写入数据的通道
var a chan<- int
// 只能读取数据的通道
var b <-chan int

通道仅用来作为标记等时可以这样用,节省空间。

// 通道类型是空结构体,更节省空间!
var notice = make(chan struct{}, 10)
// ...
// 向notice通道里写入。  struct{} 是类型,再加一个 {} 表示实例化
notice <- struct{}{}

3. worker pool (goroutine 池)

就是开启多个 goroutine 竞争执行任务。

4. select 多路复用

同一时刻有多个通道,选择其中某一个执行。

让其他未满足条件的通道同时等待,提高效率。

a := make(chan int, 1)
select{
  // 哪个满足条件就执行哪一个,有多个条件满足时随机执行一个!
  case x := <- a: 
    // ...
  case a <- 10:
    // ... 
}

以上就是go并发编程的简单知识,另外涉及到并发,就还有互斥锁和读写锁等各类锁的使用以及线程互斥和线程同步的知识,这里就不赘述了。

相关文章
|
7天前
|
监控 Java 持续交付
后端开发中的微服务架构实践与挑战####
在当今快速迭代的软件开发领域,微服务架构以其灵活性和可扩展性成为众多企业的首选。本文探讨了微服务架构的核心概念、实施策略及面临的主要挑战,旨在为后端开发者提供一个全面的指南。通过分析真实案例,揭示微服务在提升系统敏捷性的同时,如何有效应对分布式系统的复杂性问题。 ####
|
13天前
|
缓存 API 持续交付
构建高效后端服务的实践之路
【10月更文挑战第34天】在数字化时代的浪潮中,后端服务是支撑整个互联网的脊梁。本文将深入探讨如何构建一个高效的后端服务,涵盖从选择合适的编程语言和框架,到设计高性能的数据库交互、实现缓存机制、优化API设计,以及确保服务的高可用性和可扩展性。我们将通过实际代码示例,展示如何在面对复杂业务逻辑时,依然能够保持后端服务的高效与稳定。无论你是后端开发的新手,还是希望提升现有服务性能的资深开发者,这篇文章都将为你提供宝贵的实践经验和启示。
|
2天前
|
消息中间件 监控 持续交付
后端开发中的微服务架构设计与实践####
在当今快速发展的软件开发领域,微服务架构已成为构建高效、可扩展和易于维护应用的关键策略。本文将深入探讨微服务架构的核心概念、设计原则与实战技巧,通过实例解析如何在后端开发中有效实施微服务,以应对复杂业务需求和技术挑战。我们将从微服务的拆分策略、通信机制、数据管理到持续集成/持续部署(CI/CD)流程,全面剖析其背后的技术细节与最佳实践,为读者提供一份详尽的微服务架构设计与实践指南。 ####
|
1天前
|
Go 开发者
Go语言中的并发编程:掌握goroutines和channels####
本文深入探讨了Go语言中并发编程的核心概念,重点介绍了goroutines和channels的工作原理及其在实际开发中的应用。文章通过实例演示如何有效地利用这些工具来编写高效、可维护的并发程序,旨在帮助读者理解并掌握Go语言在处理并发任务时的强大能力。 ####
|
2天前
|
消息中间件 负载均衡 测试技术
后端开发中的微服务架构实践与挑战####
本文旨在探讨微服务架构在后端开发中的应用实践,深入分析其带来的优势与面临的挑战。通过剖析真实案例,揭示微服务转型过程中的关键技术决策、服务拆分策略、以及如何有效应对分布式系统的复杂性问题。文章还将提供一套评估企业是否适合采用微服务架构的框架,帮助读者更好地理解这一架构模式,并为企业的技术选型提供参考。 ####
|
11天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
6天前
|
Kubernetes API Docker
构建高效后端服务:微服务架构的深度实践与优化####
本文深入探讨了微服务架构在现代后端开发中的应用,通过剖析其核心概念、设计原则及实施策略,结合具体案例分析,展示了如何有效提升系统的可扩展性、可靠性和维护性。文章还详细阐述了微服务拆分的方法论、服务间通信的最佳实践、以及容器化与编排工具(如Docker和Kubernetes)的应用技巧,为读者提供了一份全面的微服务架构落地指南。 ####
|
12天前
|
监控 API 持续交付
后端开发中的微服务架构实践与挑战####
本文深入探讨了微服务架构在后端开发中的应用,分析了其优势、面临的挑战以及最佳实践策略。不同于传统的单体应用,微服务通过细粒度的服务划分促进了系统的可维护性、可扩展性和敏捷性。文章首先概述了微服务的核心概念及其与传统架构的区别,随后详细阐述了构建微服务时需考虑的关键技术要素,如服务发现、API网关、容器化部署及持续集成/持续部署(CI/CD)流程。此外,还讨论了微服务实施过程中常见的问题,如服务间通信复杂度增加、数据一致性保障等,并提供了相应的解决方案和优化建议。总之,本文旨在为开发者提供一份关于如何在现代后端系统中有效采用和优化微服务架构的实用指南。 ####
|
13天前
|
存储 设计模式 安全
Go语言中的并发编程:从入门到精通###
本文深入探讨了Go语言中并发编程的核心概念与实践技巧,旨在帮助读者从理论到实战全面掌握Go的并发机制。不同于传统的技术文章摘要,本部分将通过一系列生动的案例和代码示例,直观展示Go语言如何优雅地处理并发任务,提升程序性能与响应速度。无论你是Go语言初学者还是有一定经验的开发者,都能在本文中找到实用的知识与灵感。 ###
|
14天前
|
消息中间件 设计模式 运维
后端开发中的微服务架构实践与挑战####
本文深入探讨了微服务架构在现代后端开发中的应用,通过实际案例分析,揭示了其在提升系统灵活性、可扩展性及促进技术创新方面的显著优势。同时,文章也未回避微服务实施过程中面临的挑战,如服务间通信复杂性、数据一致性保障及部署运维难度增加等问题,并基于实践经验提出了一系列应对策略,为开发者在构建高效、稳定的微服务平台时提供有价值的参考。 ####
下一篇
无影云桌面