sync.Mutex 类型
sync.Mutex
类型是 Go 实现的一个互斥体。它的定义可以在 sync
目录的 mutex.go
文件中找到,内容如下:
sync.Mutex
类型的定义没有什么特别的。所有的工作都是由 sync.Lock()
和 sync.Unlock()
来做的,它们分别能加锁和解锁 sync.Mutex
互斥体。给互斥体上锁意味着没人可以操作它,直到使用 sync.Unlock()
函数解锁。
mutex.go
程序分为五部分介绍,来说明 sync.Mutex
类型的使用。
mutex.go
的第一段代码如下:
package main
import (
"fmt"
"os"
"strconv"
"sync"
"time"
)
var (
m sync.Mutex
v1 int
)
mutex.go
的第二段代码如下:
func change(i int) {
m.Lock()
time.Sleep(time.Second)
v1 = v1 + 1
if v1 % 10 == 0 {
v1 = v1 - 10*i
}
m.Unlock()
}
这个函数的关键部分是 m.Lock()
和 m.Unlock()
之间的代码。
mutex.go
的第三部分如下:
func read() int {
m.Lock()
a := v1
m.Unlock()
return a
}
同样,这个函数的关键部分也由 m.Lock()
和 m.Unlock()
表达式限定。
mutex.go
的第四部分代码如下:
func main() {
if len(os.Args) != 2 {
fmt.Println("Please give me an integer!")
return
}
numGR, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Println(err)
return
}
var waitGroup sync.WaitGroup
mutex.go
的最后一段代码如下:
fmt.Printf("%d ", read())
for i := 0; i < numGR; i++ {
waitGroup.Add(1)
go func(i int) {
defer waitGroup.Done()
change(i)
fmt.Printf("-> %d", read())
}(i)
}
waitGroup.Wait()
fmt.Printf("-> %d\n", read())
}
执行 mutex.go
将产生如下输出:
如果您从 change()
函数移除 m.Lock()
和 m.Unlock()
表达式,这个程序会产生类似如下输出:
输出中发生改变的原因是所有 goroutines 同时去修改共享变量,这也是随机输出的主要原因。