Golang 并发&同步的详细原理和使用技巧

本文深入探讨了Golang的并发与同步原理,包括CSP并发模型、goroutine、context、sync包(Mutex、RWMutex、WaitGroup)以及Channel的使用。强调了通过同步控制避免并发访问内存数据的错乱,介绍了context在控制子协程生命周期中的作用,以及sync包中锁的使用最佳实践。同时,对比了WaitGroup和Channel在并发同步中的差异,并提到了errgroup在处理并发错误中的应用。
摘要由CSDN通过智能技术生成

Golang 并发&同步的详细原理和使用技巧

Golang 并发概要说明

并发模型

Golang 的并发模型属于一种很典型的 CSP(communicating sequential processes) 并发模型,其核心是不要通过共享内存来通信,而应该通过通信来共享内存。具体实现,就是通过 goroutine 来实现并发,然后并发的 goroutine 之间通过 Channel 来进行通信; 为此,Golang 的并发也有两个明显特点:

  1. Golang 非常善于并发,可以很简单的来实现(goroutine),直接一个 go 语句基就搞定,通过提高并发可以显著提高处理效率。
  2. Golang 的 goroutine 并发协程之间一般是采用通信的方式来共享变量或者逻辑交互,而这其中就可以结合 channel 来让并发协程之间进行共享数据,而 channel 就是各个 goroutine 之间通信的管道。

go 关键字实现并发

Golang 并发是通过 goroutine 协程来实现的,通过 go 关键字可以非常简单的启动一个协程;通过 go 关键字启动协程之后, 主进程并不会等待协程的执行,而是继续执行直至结束。因此,如果父子进程之间要有控制关系的话,就需要同步机制来保证。

Golang 并发&同步的设计和实现

为何需要同步控制

Go 既然天然支持并发,并且可以很简单的实现并发编程,那么这些并发的协程之间,如果同时访问访问内存中的同一个数据,在没有同步的机制下,那么同一个数据的访问一定会出现错乱,因此,在并发的场景,一定要通过同步机制才能确保同一内存数据的正确访问。

并发和 context

当需要进行多批次的计算任务同步,或者需要一对多的协作流程的时候;通过 Context 的关联关系(go 的 context 被设计为包含了父子关系),我们就可以控制子协程的生命周期,而其他的同步方式是无法控制其生命周期的,只能是被动阻塞等待完成或者结束。context 控制子协程的生命周期,是通过 context 的 context.WithTimeout 机制来实现的,这个是一般系统中或者底层各种框架、库的普适用法。

context 对并发做一些控制包括 Context Done 取消、截止时间取消 context.WithDeadline、超时取消 context.WithTimeout 等。

一个简单的 context.WithTimeout 示例如下:

	package main
	
	import (
		"fmt"
		"sync"
		"time"
	
		"golang.org/x/net/context"
	)
	
	var (
		wg sync.WaitGroup
	)
	
	func work(ctx context.Context) error {
		defer wg.Done()
	
		for i := 0; i < 1000; i++ {
			select {
			case <-time.After(2 * time.Second):
				fmt.Println("Do work ", i)
	
			// we received the signal of cancelation in this channel
			case <-ctx.Done():
				fmt.Println("Cancel th
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值