Go实现并发与并行,这才是正确打开方式!

简介: Go实现并发与并行,这才是正确打开方式!

并发(Concurrency)与并行(Parallelism)是两个容易混淆的概念。本文将阐明两者的内涵、实现机制、应用场景、优劣势等方面的区别。

1、并发是什么

并发是一种处理多任务的能力,它意味着程序可以同时处理多段指令流,但是执行顺序未必确定,也不要求同时执行。

例如一个 Web 服务器,可以同时处理请求 A、请求 B,但是执行顺序由系统调度,A 和 B 不一定同时执行。

Go 语言使用 Goroutine 实现并发,Goroutine 是轻量级线程,由 Go 运行时(Runtime)负责调度


func server() {  go handleRequestA()  go handleRequestB()}

Goroutine 具有启动迅速、资源消耗少的优点,非常适合大规模并发。

2、并行是什么

并行则要求同时执行多道指令,真正做到同时进行,以提高程序执行速度。并行依赖多核 CPU。

Go 语言可以检测 CPU 核数量,将任务并行分配给每个核心执行



func main() {  cpu := runtime.NumCPU()
  var wg sync.WaitGroup  wg.Add(cpu)  for i := 0; i < cpu; i++ {    go func() {      defer wg.Done()      // 并行执行任务    }()  }
  wg.Wait() // 等待所有任务结束}

这样就实现了真正的并行计算。另外,GPU 带来了更强大的并行计算能力,可用于深度学习等场景。

3、并发与并行的区别

并发与并行存在一些关键区别:

并发强调同时处理多任务,而并行强调同时执行多任务。

并发使用线程、Goroutine 实现,并行使用多核心实现。

并发关注任务处理能力,并行关注执行速度。

简单来说:

并发是处理,并行是执行。

并发可以通过线程等实现,并行依赖多核。

4


// 并发下载多个URLfunc download(urls []string) {  ch := make(chan string)  for _, url := range urls {    go func(url string) {      resp := downloadUrl(url)      ch <- resp // 返回结果    }(url)  }    for range urls {    <-ch // 获取结果  }}

上面的示例使用 Goroutine 实现了并发下载任务,然后通过 Channel 获取每个下载的结果。

这里强调的是处理多任务的能力,而不是同时执行下载。

5

func calculate(matrix [][]float32) [][]float32 {  cpu := runtime.NumCPU()  chs := make([]chan []float32, cpu)    // 并行计算   for i:= 0; i< cpu; i++ {    ch := make(chan []float32)    go func(m [][]float32, ch chan []float32) {      ch <- parallelCalc(m)    }(matrix, ch)    chs[i] = ch  }
  // 合并结果  result := make([][]float32, 0)  for _, ch := range chs {    item := <-ch    result = append(result, item)  }
  return result}

这里根据 CPU 数量,将矩阵任务并行分配给每个核心处理,然后合并结果,真正达到了并行计算的效果。

6、并发的优点

相比并行,并发更难实现,但其主要优点是:

更快响应用户交互请求

更好地利用系统资源

代码逻辑组织更合理

显示进度及状态更方便

Go 并发编程可以大大提升服务器响应效率。

7、并行的优点

并行编程的优势在于:

极大提升计算吞吐量

更快完成计算密集型任务

更高的运算效率

使得并行非常适合科学计算、数据分析等场景。

8、总结

并发强调同时处理多任务,并行强调同时执行

并发使用线程等机制,并行利用多核实现

并发偏重任务量,并行注重执行速度

两者在一定程度上可以联用,发挥各自优势

Go 语言很好地支持了并发和并行。理解两者的区别和各自应用场景,可以设计出更合理、高效的程序。

目录
相关文章
|
5月前
|
Shell Go API
Go语言grequests库并发请求的实战案例
Go语言grequests库并发请求的实战案例
|
6月前
|
Go
Go 语言为什么不支持并发读写 map?
Go 语言为什么不支持并发读写 map?
|
3月前
|
存储 负载均衡 监控
如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
在数字化时代,构建高可靠性服务架构至关重要。本文探讨了如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
80 1
|
3月前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
4月前
|
Java 大数据 Go
Go语言:高效并发的编程新星
【10月更文挑战第21】Go语言:高效并发的编程新星
75 7
|
3月前
|
并行计算 安全 Go
Go语言的并发特性
【10月更文挑战第26天】Go语言的并发特性
32 1
|
4月前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
4月前
|
安全 Go 开发者
破译Go语言中的并发模式:从入门到精通
在这篇技术性文章中,我们将跳过常规的摘要模式,直接带你进入Go语言的并发世界。你将不会看到枯燥的介绍,而是一段代码的旅程,从Go的并发基础构建块(goroutine和channel)开始,到高级模式的实践应用,我们共同探索如何高效地使用Go来处理并发任务。准备好,让Go带你飞。
|
4月前
|
安全 Go 调度
探索Go语言的并发之美:goroutine与channel
在这个快节奏的技术时代,Go语言以其简洁的语法和强大的并发能力脱颖而出。本文将带你深入Go语言的并发机制,探索goroutine的轻量级特性和channel的同步通信能力,让你在高并发场景下也能游刃有余。
|
4月前
|
Go 数据处理 调度
Go语言中的并发模型:解锁高效并行编程的秘诀
本文将探讨Go语言中独特的并发模型及其在现代软件开发中的应用。通过深入分析 Goroutines 和 Channels,我们将揭示这一模型如何简化并行编程,提升应用性能,并改变开发者处理并发任务的方式。不同于传统多线程编程,Go的并发方法以其简洁性和高效性脱颖而出,为开发者提供了一种全新的编程范式。

热门文章

最新文章