Golang 高效并发模式

简介: 前几篇对并发编程基础元素goroutine、channel、sync包有所了解,接下来可利用这部分内容组成可使用的并发模式。

前几篇对并发编程基础元素goroutine、channel、sync包有所了解,接下来可利用这部分内容组成可使用的并发模式。

for select 循环模式

多路复用的并发模式,直到满足某条件退出for循环

// 模式1:
for{
    select{
        case <-done
          return
    default:
      //执行具体的内容
    }
}

// 模式2:
for _,val := range []int{
  select {
    case <-done:
     return
    case resCh <-val:
    ...
    if .. {
      done <- ??
    }
  }
}
  • 模式1:一直执行default语句中的任务,直到执行done后被关闭停止
  • 模式2:有限循环,resCh接收循环的值,可通过满足某条件将值传递给done,这样就可以退出当前循环,或者其他方式

select timeout模式

请求数据时,因网络不同响应时间也不同,为避免出现一直等待那些超时请求,我们需要设置一个超时时间,可使用select timeout模式

select {
    case v := <-result
      ...
    case <-time.After(5 * time.Second)
       fmt.Println("网络访问超时了")
}

主要通过time.After函数设置一个超时时间,防止因异常导致select语句无限等待。如果存在Context,可优先使用context.WithTimeout函数

Pipeline模式

管道模式(流水线模式),类似一个流水线生产,经过多个工序作业完成最后的成品。

  • 流水线由多道工序构成,每道工序通过channel将数据传递到下一个工序,即每道工序的入参都是上游工序的返回值,产生的值继续传递给下游工序
  • 每道工序对应一个函数,函数中有协程和channal,函数处理数据,并把它放在channel中,最后返回channel给下一道工序使用
  • 组织者将所有工序串联起来,形成完整的流水线
// 
func main(){
  first := build1()
  second := build2(first)
  third := build3(second)
}
//工序1
func build1(in <-chan string) <-chan string{
  out := make(chan string)
  
  go func(){
    defer close(out)
    for c:= range in{
       out <- "组装(“+c+”)"
    }
  }()
  
  return out
}
// 工序2
func build2(in <-chan string) out chan string{
  ...
}
// 工序3
func build3(in <-chan string) out chan string{
  ...
}

扇出和扇入模式

扇出:多个函数可以从同一个通道读取数据,直到通道关闭

扇入:一个函数可以从多个通道读取数据,直到通道关闭

func main(){
  in := gen(1)
  
  c1 := sq(in)
  c2 := sq(in)
  
  for n := range merge(c1,c2){
    fmt.Println(n) 
  }
}

func sq(in <-chan string) chan string{
  out := make(chan string)
  go func(){
    ...
  }
  return out 
}
目录
相关文章
|
2月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
80 4
|
4月前
|
测试技术 Go
golang 的重试弹性模式怎么设计?
Golang的可重构弹性模式通过`Retrier`实现了重试逻辑。创建`Retrier`需指定重试间隔(隐含重试次数)及错误分类器,决定哪些错误需重试。示例代码展示了如何创建一个重试器并执行带有重试逻辑的工作函数。`Retrier`结构体包含重试间隔、分类器等字段。
|
4月前
|
测试技术 Go
golang 的重试弹性模式
Golang 中的重试机制实现了一个名为 `Retrier` 的结构体,用于实现弹性模式。`Retrier` 创建时需要指定重试间隔(如常量间隔或指数递增间隔)和错误分类器。分类器决定了哪些错误应被重试。默认情况下,如果未提供分类器,则使用默认分类器,它简单地将非 nil 错误标记为应重试。提供了三种分类器:默认、白名单和黑名单。`Run` 和 `RunCtx` 是执行重试的函数,后者接受上下文以便处理超时。通过 `calcSleep` 计算带有随机抖动的休眠时间,增加重试的不可预测性,减少并发冲突。如果达到最大重试次数或上下文超时,重试将停止。
|
6月前
|
前端开发 Go
Golang深入浅出之-Go语言中的异步编程与Future/Promise模式
【5月更文挑战第3天】Go语言通过goroutines和channels实现异步编程,虽无内置Future/Promise,但可借助其特性模拟。本文探讨了如何使用channel实现Future模式,提供了异步获取URL内容长度的示例,并警示了Channel泄漏、错误处理和并发控制等常见问题。为避免这些问题,建议显式关闭channel、使用context.Context、并发控制机制及有效传播错误。理解并应用这些技巧能提升Go语言异步编程的效率和健壮性。
308 5
Golang深入浅出之-Go语言中的异步编程与Future/Promise模式
|
6月前
|
Go
深度探讨 Golang 中并发发送 HTTP 请求的最佳技术
深度探讨 Golang 中并发发送 HTTP 请求的最佳技术
118 4
|
6月前
|
存储 缓存 安全
Golang深入浅出之-Go语言中的并发安全容器:sync.Map与sync.Pool
Go语言中的`sync.Map`和`sync.Pool`是并发安全的容器。`sync.Map`提供并发安全的键值对存储,适合快速读取和少写入的情况。注意不要直接遍历Map,应使用`Range`方法。`sync.Pool`是对象池,用于缓存可重用对象,减少内存分配。使用时需注意对象生命周期管理和容量控制。在多goroutine环境下,这两个容器能提高性能和稳定性,但需根据场景谨慎使用,避免不当操作导致的问题。
185 7
|
6月前
|
安全 Go 开发者
Golang深入浅出之-Go语言中的CSP模型:深入理解并发哲学
【5月更文挑战第2天】Go语言的并发编程基于CSP模型,强调通过通信共享内存。核心概念是goroutines(轻量级线程)和channels(用于goroutines间安全数据传输)。常见问题包括数据竞争、死锁和goroutine管理。避免策略包括使用同步原语、复用channel和控制并发。示例展示了如何使用channel和`sync.WaitGroup`避免死锁。理解并发原则和正确应用CSP模型是编写高效安全并发程序的关键。
153 7
|
6月前
|
安全 Go
Golang深入浅出之-Go语言中的并发安全队列:实现与应用
【5月更文挑战第3天】本文探讨了Go语言中的并发安全队列,它是构建高性能并发系统的基础。文章介绍了两种实现方法:1) 使用`sync.Mutex`保护的简单队列,通过加锁解锁确保数据一致性;2) 使用通道(Channel)实现无锁队列,天生并发安全。同时,文中列举了并发编程中常见的死锁、数据竞争和通道阻塞问题,并给出了避免这些问题的策略,如明确锁边界、使用带缓冲通道、优雅处理关闭以及利用Go标准库。
438 5
|
6月前
|
安全 Go 开发者
Golang深入浅出之-Go语言中的CSP模型:深入理解并发哲学
【5月更文挑战第1天】Go语言基于CSP理论,借助goroutines和channels实现独特的并发模型。Goroutine是轻量级线程,通过`go`关键字启动,而channels提供安全的通信机制。文章讨论了数据竞争、死锁和goroutine泄漏等问题及其避免方法,并提供了一个生产者消费者模型的代码示例。理解CSP和妥善处理并发问题对于编写高效、可靠的Go程序至关重要。
139 2
|
6月前
|
设计模式 Go 调度
Golang深入浅出之-Go语言中的并发模式:Pipeline、Worker Pool等
【5月更文挑战第1天】Go语言并发模拟能力强大,Pipeline和Worker Pool是常用设计模式。Pipeline通过多阶段处理实现高效并行,常见问题包括数据竞争和死锁,可借助通道和`select`避免。Worker Pool控制并发数,防止资源消耗,需注意任务分配不均和goroutine泄露,使用缓冲通道和`sync.WaitGroup`解决。理解和实践这些模式是提升Go并发性能的关键。
75 2