Go的sync包中 Mutex 使用

Go的sync包中 Mutex 使用

背景

多个协程操作中经常出现脏读写的情况,这种情况下需要使用互斥锁,保证在对协程共享区域操作的原子性。

如下示例:
启动了 100个协程,每个协程累加 100 次,在没有脏读写的情况下,最后结果应该是 100 * 100 = 10000

package main

import (
	"fmt"
	"sync"
)

func main() {
   var count = 0
   var wg  sync.WaitGroup
   wg.Add(100)
   for i :=0; i< 100; i++ {
      go func(){
         defer wg.Done()
         for j := 0; j< 100; j ++ {
            count ++
         }
      }()
   }
   wg.Wait()
   fmt.Println(count)
}

但是实际结果一直小于 10000
在这里插入图片描述

互斥锁

count ++ 操作, 分为三个步骤

  • 在协程的共享区域取出 count 当前值
  • 当前值加一
  • 加一后的值写回协程共享区域
    这时需要使用互斥锁, 来保证对 count++ 的三个操作过程中没有其他协程进行读写。
    Go的Sync 包提供了Mutex, 读写互斥的锁, 来保证只有一个协程对数据进行读写操作。 以保证 count++操作的原子性
    如下示例:

package main

import (
	"fmt"
	"sync"
)

func main() {
   var count = 0
   // 声明Mutex变量
   var mu sync.Mutex
   var wg  sync.WaitGroup
   wg.Add(100)
   for i :=0; i< 100; i++ {
      go func(){
         defer wg.Done()
         for j := 0; j< 100; j ++ {
            // 添加锁
            mu.Lock()
            count ++
            // 解锁
            mu.Unlock()
         }
      }()
   }
   wg.Wait()
   fmt.Println(count)
}

mu.Lock()mu.Unlock() 之间的代码可以保证在操作只会被一个协程执行。这样执行结果就是 10000 了
在这里插入图片描述

注意

mu.Lock()mu.Unlock() 必须成对出现,在忘掉 Unlock 的情况下,锁获取后永远不会得到释放,其他 的线程/协程会永远处于阻塞状态,永远获取不到锁,在忘掉 Lock 的情况下,直接 Unlock 一个未加锁的 Mutex,会导致程序 panic。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`.Mutex` 是 Go 语言标准库 `sync` 包中的一种同步原语,用于实现互斥锁(Mutex)。互斥锁是一种常用的并发控制机制,用于保护临界区代码,在同一时间只允许一个线程或 goroutine 进入临界区执行。 `sync.Mutex` 是一个结构体类型,它包含了互斥锁的状态和相关的方法。通过使用互斥锁,可以确保在同一时间只有一个 goroutine 能够获取锁,并执行被保护的临界区代码。 下面是一个使用 `sync.Mutex` 的简单示例: ```go package main import ( "fmt" "sync" ) var counter int var mutex sync.Mutex func increment() { mutex.Lock() // 获取互斥锁 defer mutex.Unlock() // 在函数退出时释放互斥锁 counter++ } func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() increment() }() } wg.Wait() fmt.Println("Final counter value:", counter) } ``` 在上面的示例中,我们定义了一个全局变量 `counter` 和一个 `sync.Mutex` 类型的变量 `mutex`。在 `increment` 函数中,我们首先通过调用 `mutex.Lock()` 来获取互斥锁,然后执行 `counter++` 以增加计数器的值,最后在函数退出时调用 `mutex.Unlock()` 来释放互斥锁。 在主函数中,我们启动了 10 个 goroutine 来并发地调用 `increment` 函数。通过使用互斥锁,我们确保每次只有一个 goroutine 能够获取互斥锁并执行临界区代码,从而避免了竞态条件(race condition)。 `sync.Mutex` 在并发编程中是一个常用的工具,可以有效地保护共享资源的访问。当多个 goroutine 需要访问同一临界区时,使用互斥锁可以确保线程安全,并避免数据竞争。 希望以上解释对你有帮助!如有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值