golang value并发安全的另一种玩法是怎样的

2023-04-14 01:02:00 并发 是怎样 玩法

Golang 的并发安全的另一种玩法是通过使用 sync.Mutex 来实现的。

首先,我们来看看什么是 Mutex 。 Mutex 是一个互斥锁,可以使用它来保证在任意时刻,只有一个 goroutine 能够访问某个共享资源。

使用 Mutex 的时候需要注意以下几点:

1. 在使用之前必须先将其初始化,通过 sync.Mutex 函数来实现

2. 当一个 goroutine 获取了锁之后,其他 goroutine 就只能等待锁被释放

3. 使用完毕后要及时将锁释放

下面我们来看一个简单的例子:

```

package main

import (

"fmt"

"sync"

)

var counter int

func main() {

var wg sync.WaitGroup

wg.Add(2)

var mu sync.Mutex

go func() {

defer wg.Done()

for i := 0; i < 10; i++ {

mu.Lock()

counter++

fmt.Println("Counter: ", counter)

mu.Unlock()

}

}()

go func() {

defer wg.Done()

for i := 0; i < 10; i++ {

mu.Lock()

counter--

fmt.Println("Counter: ", counter)

mu.Unlock()

}

}()

wg.Wait()

}

```

上面的代码中我们使用了两个 goroutine 来对 counter 进行操作,分别是自增和自减。我们使用了一个叫做 mutex 的锁来保证在任意时刻只有一个 goroutine 能够访问 counter 变量。

我们可以看到在每次对 counter 变量的操作前后都加上了锁的获取和释放。当一个 goroutine 获取了锁之后,其他 goroutine 就只能等待锁被释放,直到能够获取锁。

运行上面的代码,我们会看到输出结果是按顺序的,这就说明我们的代码是并发安全的。

需要注意的是,我们使用锁的时候一定要注意避免死锁的发生。死锁是指两个或者多个 goroutine 互相等待对方释放锁,从而导致程序永远无法继续执行下去的情况。

例如,我们可以将上面的代码修改一下,让它发生死锁:

```

package main

import (

"fmt"

"sync"

)

var counter int

func main() {

var wg sync.WaitGroup

wg.Add(2)

var mu sync.Mutex

go func() {

defer wg.Done()

mu.Lock()

for i := 0; i < 10; i++ {

counter++

fmt.Println("Counter: ", counter)

}

mu.Unlock()

}()

go func() {

defer wg.Done()

mu.Lock()

for i := 0; i < 10; i++ {

counter--

fmt.Println("Counter: ", counter)

}

mu.Unlock()

}()

wg.Wait()

}

```

上面的代码中我们将两个 goroutine 都锁住了,导致它们互相等待对方释放锁,从而导致程序发生死锁。

我们可以通过在锁的使用上加以区分来避免死锁的发生,例如:

```

package main

import (

"fmt"

"sync"

)

var counter int

func main() {

var wg sync.WaitGroup

wg.Add(2)

var mu sync.Mutex

go func() {

defer wg.Done()

for i := 0; i < 10; i++ {

mu.Lock()

counter++

fmt.Println("Counter: ", counter)

mu.Unlock()

}

}()

go func() {

defer wg.Done()

for i := 0; i < 10; i++ {

mu.Lock()

counter--

fmt.Println("Counter: ", counter)

mu.Unlock()

}

}()

wg.Wait()

}

```

上面的代码中我们将两个 goroutine 分开锁住了,这样就不会发生死锁了。

最后,需要注意的是,在使用锁的时候,一定要及时将锁释放,否则会导致程序发生错误。

相关文章