工作用Go: 异步任务怎么写2 | 简单 Go 并发: 任务编排

简介: 工作用Go: 异步任务怎么写2 | 简单 Go 并发: 任务编排

go01.jpeg

本文为 工作用Go: 异步任务怎么写 系列的2


上面的例子, 常见有 3 种解决方案:


  • 方案1: 等子协程执行完
funcTestTask(t*testing.T) {
gotask()
time.Sleep(time.Second) // 等待子协程执行完log.Print("req done")
}
functask() {
// 模拟耗时任务time.Sleep(time.Second)
log.Print("task done")
}


  • 方案2: 使用 WaitGroup
funcTestTask(t*testing.T) {
varwgsync.WaitGroupwg.Add(1)
gofunc() {
task()
wg.Done()
 }()
wg.Wait()
log.Print("req done")
}
functask() {
// 模拟耗时任务time.Sleep(time.Second)
log.Print("task done")
}

WaitGroup 其实很好理解, 就是同时等待一组任务完成, 它分为 3 步: 1. Add: 总共有多少任务; 2. Done(): 表示任务执行完; 3. Wait(): 等待所有任务完成


  • 方案3: 使用 Go 的并发语言 chan
funcTestTask(t*testing.T) {
ch :=make(chanstruct{}) // 初始化 changofunc() {
task()
ch<-struct{}{} // 发送到 chan }()
<-ch// 从 chan 获取log.Print("req done")
}
functask() {
// 模拟耗时任务time.Sleep(time.Second)
log.Print("task done")
}


Go基础知识: 通过 chan T 就可以申明 T 类型的 chan, 供协程间进行通信; struct{} 是 Go 中 0 memory use(0内存占用)类型, 适合上面使用 chan 进行 控制 而不需要 数据 进行通信的情况


虽然只是3个简单的 demo code, Go 提供的 2 种并发能力都有展示:

  • 传统并发原语: 大部分集中在sync包下, 上面案例2中的 sync.WaitGroup 就是其中之一
  • Go 基于 CSP 的并发编程范式: 包括 go chan select, 上面的案例3中展示了 go+chan 的基本用法


简单 Go 并发讲完了, 那任务编排又是啥? 其实, 某等程度上, 任务编排=异步, 任务需要 分工 完成时, 也就是一个任务相对于另一个任务需要 异步处理. 而任务编排, 恰恰是 Go 语言中基于 chan 进行并发编程的强项.


Go 中有一个大的方向,就是任务编排用 Channel,共享资源保护用传统并发原语。


回到最初的代码, 在实际使用中, 到底使用的是哪种方案呢? 答案是 方案1. 看看接近真实场景的代码

funcTestTrace(t*testing.T) {
for { // 服务以 daemon 的方式持续运行// 不断处理用户的请求  {
gotask()
log.Print("req done")
  }
 }
}
functask() {
// 模拟耗时任务time.Sleep(time.Second)
log.Print("task done")
}


也就是真实场景下, 主协程所在的 server 会一直常驻, 请求(request)所有的子协程不用担心还没执行完就被强制退出了.

目录
相关文章
|
3天前
|
人工智能 Go 调度
掌握Go并发:Go语言并发编程深度解析
掌握Go并发:Go语言并发编程深度解析
|
3天前
|
安全 Java Go
Java vs. Go:并发之争
【4月更文挑战第20天】
25 1
|
3天前
|
Go 调度 开发者
CSP模型与Goroutine调度的协同作用:构建高效并发的Go语言世界
【2月更文挑战第17天】在Go语言的并发编程中,CSP模型与Goroutine调度机制相互协同,共同构建了高效并发的运行环境。CSP模型通过通道(channel)实现了进程间的通信与同步,而Goroutine调度机制则确保了并发任务的合理调度与执行。本文将深入探讨CSP模型与Goroutine调度的协同作用,分析它们如何共同促进Go语言并发性能的提升。
|
3天前
|
存储 算法 编译器
掌握Go语言:探索Go语言递归函数的高级奥秘,优化性能、实现并发、解决算法难题(28)
掌握Go语言:探索Go语言递归函数的高级奥秘,优化性能、实现并发、解决算法难题(28)
|
3天前
|
SQL Go 数据库
【Go语言专栏】Go语言中的事务处理与并发控制
【4月更文挑战第30天】Go语言在数据库编程中支持事务处理和并发控制,确保ACID属性和多用户环境下的数据完整性。`database/sql`包提供事务管理,如示例所示,通过`Begin()`、`Commit()`和`Rollback()`执行和控制事务。并发控制利用Mutex、WaitGroup和Channel防止数据冲突。结合事务与并发控制,开发者可处理复杂场景,实现高效、可靠的数据库应用。
|
3天前
|
Cloud Native Go 云计算
多范式编程语言Go:并发与静态类型的结合
Go语言是Google于2007年开发的开源编程语言,旨在提高程序开发和部署的效率。它的独特特征在于结合了并发处理与静态类型系统,提供了简洁、高效、并行处理能力的编程体验。本文将探讨Go语言的特点、应用场景以及其在现代软件开发中的优势。
|
3天前
|
安全 Go
Golang深入浅出之-Go语言中的并发安全队列:实现与应用
【5月更文挑战第3天】本文探讨了Go语言中的并发安全队列,它是构建高性能并发系统的基础。文章介绍了两种实现方法:1) 使用`sync.Mutex`保护的简单队列,通过加锁解锁确保数据一致性;2) 使用通道(Channel)实现无锁队列,天生并发安全。同时,文中列举了并发编程中常见的死锁、数据竞争和通道阻塞问题,并给出了避免这些问题的策略,如明确锁边界、使用带缓冲通道、优雅处理关闭以及利用Go标准库。
26 5
|
3天前
|
存储 缓存 安全
Golang深入浅出之-Go语言中的并发安全容器:sync.Map与sync.Pool
Go语言中的`sync.Map`和`sync.Pool`是并发安全的容器。`sync.Map`提供并发安全的键值对存储,适合快速读取和少写入的情况。注意不要直接遍历Map,应使用`Range`方法。`sync.Pool`是对象池,用于缓存可重用对象,减少内存分配。使用时需注意对象生命周期管理和容量控制。在多goroutine环境下,这两个容器能提高性能和稳定性,但需根据场景谨慎使用,避免不当操作导致的问题。
35 4
|
3天前
|
安全 Go 开发者
Golang深入浅出之-Go语言中的CSP模型:深入理解并发哲学
【5月更文挑战第2天】Go语言的并发编程基于CSP模型,强调通过通信共享内存。核心概念是goroutines(轻量级线程)和channels(用于goroutines间安全数据传输)。常见问题包括数据竞争、死锁和goroutine管理。避免策略包括使用同步原语、复用channel和控制并发。示例展示了如何使用channel和`sync.WaitGroup`避免死锁。理解并发原则和正确应用CSP模型是编写高效安全并发程序的关键。
35 4
|
3天前
|
安全 Go 开发者
Golang深入浅出之-Go语言中的CSP模型:深入理解并发哲学
【5月更文挑战第1天】Go语言基于CSP理论,借助goroutines和channels实现独特的并发模型。Goroutine是轻量级线程,通过`go`关键字启动,而channels提供安全的通信机制。文章讨论了数据竞争、死锁和goroutine泄漏等问题及其避免方法,并提供了一个生产者消费者模型的代码示例。理解CSP和妥善处理并发问题对于编写高效、可靠的Go程序至关重要。
26 2