学到了!将缓冲 channel 当做 Mutex 来使用

本文探讨了如何使用Go语言中的缓冲channel作为互斥锁的替代方案。通过一个示例展示了如何利用缓冲为1的channel来同步多个goroutine对文件的写入操作,确保每次只有一个goroutine在执行。文章强调了缓冲channel在阻塞和解锁行为上的特性,以及如何通过WaitGroup确保所有goroutine完成任务。
摘要由CSDN通过智能技术生成

点击上方蓝色“Golang来啦”关注我哟

加个“星标”,天天 15 分钟,掌握 Go 语言

via:
https://mipsmonsta.medium.com/golang-using-buffered-channel-like-a-mutex-9c7c80ec5c27
作者:Mipsmonsta

大家好,我是四哥。

原文如下:


作为 Go 官方包的一部分,sync 包有下面这段声明:

sync 包提供了基本的同步原语,例如互斥锁。除了 Once 和 WaitGroup 类型之外,大多数其他类型都是为底层函数库准备的。通过 channel 和通信更好地完成更高级别的同步.

在你能找到的关于允许并发访问的绝大多数例子中,很多都是使用互斥锁来解决问题。然而,几乎很少有示例给我们展示如何使用 channel 提供同步机制。所以,这篇文章我们就来讨论下。

互斥锁的特性

为了使互斥锁起作用,访问共享变量时需要加锁,操作完成之后需要解锁。相同的互斥锁不允许多次加锁,以免出现竞态条件。

无缓冲 channel 及其不足之处

如果没有接收方,发送者将会阻塞;相同地,如果没有发送方,接收者将会阻塞。基于这种特性,所以我们不能将无缓冲的 channel 作为锁来使用。

我们来看看缓冲 channel 是否可以当做互斥锁来使用。

缓冲为 1 的 channel 的特性及其可取之处

缓冲大小为 1 的 channel 具有如下的特性:如果缓冲满了,发送时将会阻塞;如果缓存腾空,发送时就会解除阻塞。

显然,这种 channel 的阻塞特性是可取的,与互斥锁的特性做个对比:

缓冲满时 <--> 上锁

缓冲腾空 <--> 解锁

我们一起通过代码演示下这种特性。

演示:如何将缓冲 channel 作为 “锁” 来使用

我们假设有一列名字需要写入到文件中,每个名字需要连续写 1000 次,且不允许不同名字出现交叉情况。

package main
import (
 "errors"
 "fmt"
 "os"
 "sync"
)
func main() {
 file, err := os.Create("record.txt")

 defer func() {
  if err := recover(); err != nil {
   fmt.Printf("Error encounter: %w", err)
  }
  file.Close()
 }()
 if err != nil {
  panic(errors.New("Cannot create/open file"))
 }
 ss := []string{ //string slice literals
  "James",
  "Avery",
  "Peter",
  "John",
  "Beau",
 }
 chanLock := make(chan int, 1) //1
 var wg sync.WaitGroup
 for _, str := range ss { //2
  wg.Add(1) //amended thanks to response from Wang
  //Sheng
  go func(aString string) {

   chanLock <- 1 //3
   for i := 0; i < 1000; i++ {
    file.WriteString(aString + "\n")
   }
   <-chanLock //4
   wg.Done() //5
  }(str) //pass by value
 }
 wg.Wait()
}

上面的代码中,//1 我们创建了缓冲为 1 的 channel。//2 我们创建了个数与名字数量相同的 goroutine。//3 相当于加锁,//4 相当于解锁,这样就实现了多 goroutine 之间同步地将名字写入到 record.txt 文件,但每次只会有一个 goroutine 操作该文件。

需要注意的是,我们通过 WaitGroup 来保证子 goroutine 完成任务之前,主协程不会退出。

希望这篇文章对你有帮助,enjoy coding!

推荐阅读:

使用context、WaitGroup优雅处理goroutine

【实战项目】使用 Go 语言开发一个并发文件下载器

2022 必读 Go 图书推荐

对了,看完文章,记得点击下方的卡片。关注我哦~ 👇👇👇



这是持续翻译的第 27/100 篇优质文章。
如果你有想交流的话题,欢迎留言。



如果您的朋友也在学习 Go 语言,相信这篇文章对 TA 有帮助,欢迎转发分享给 TA,非常感谢!97121dec40034890ddf999bf16848e72.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Seekload

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值