Golang 如何使用Mutex

Golang 如何使用Mutex

为了理解为什么 Mutex 在Go中对编写更好更准确的并发程序起着重要的作用,我们必须首先了解一个叫做 Race Conditions 的概念 。 让我们先了解一下什么是竞赛条件,我们如何编写一个具有竞赛条件的并发程序,以及我们如何在该程序中引入 互斥 来使其准确。

竞赛条件

竞赛条件 是指多个 goroutine 试图访问和修改同一资源的情况。它可能是一个 goroutines 试图增加一个特定变量的值,而其他 goroutines 同时试图访问它,或者它可能是多个 goroutines 同时试图增加一个特定变量的值。

应该注意的是,只有当我们为某一特定变量提供了 写入 权限时,才会出现竞赛条件。如果只提供了 读的 权限,那么就不会有任何问题,因为即使多个 goroutines 试图读取一个值,读也不会造成任何问题。

例子1

现在让我们假设我们想为一个本地银行写一个应用程序,银行只支持一个单一的功能,即把钱存入银行。我们可以用多个 goroutines 来表示这种情况,因为有可能有很多人同时试图存入金额。

请看下面的代码,它描述了这种情况。

package main

import (
   "fmt"
   "sync"
)

var (
   balance int
   wg sync.WaitGroup
)

func Deposit(amount int) {
   balance = balance + amount
   wg.Done()
}

func main() {
   wg.Add(3)
   go Deposit(100)
   go Deposit(200)
   go Deposit(300)
   wg.Wait()

   fmt.Println("Balance is:", balance)
}

在上面的例子中,我们可以看到,除了 函数goroutine之外,还有三个 goroutine 。这三个 goroutine 正在调用 deposit 函数,由于这个原因,出现了一个竞赛条件,因为我们还没有处理它。

“race “ 标志的帮助下,人们可以确认竞赛条件的存在。

go run -race main.go

注意种族标志 是用来检查任何Golang代码是否有种族条件。

输出

Balance is: 600

为了使代码更加准确,并消除这种竞赛条件,我们利用 Mutex ,也称为 互斥 ,它可以防止并发进程在执行另一个任务时访问关键数据。

例2

请看下面的代码,我们在上面的代码中使用了 Mutex ,以消除竞赛条件。

package main

import (
   "fmt"
   "sync"
)

var (
   balance int
   wg    sync.WaitGroup
   mu    sync.Mutex
)

func Deposit(amount int) {
   mu.Lock()
   defer mu.Unlock()
   balance = balance + amount
   wg.Done()
}

func main() {
   wg.Add(3)
   go Deposit(100)
   go Deposit(200)
   go Deposit(300)
   wg.Wait()

   fmt.Println("Balance is:", balance)
}

输出

现在,如果我们运行命令, go run -race main.go ,那么我们就不会看到任何提到的竞赛条件。我们得到的输出如下所示。

Balance is: 600

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程