- 前言
- Go 与操作系统
- Go 内部机制
- Go 基本数据类型
- 4 组合类型的使用
- 5 数据结构
- 6 Go package 中不为人知的知识
- 7 反射和接口
- 8 Go UNIX 系统编程
- 08.1 关于 UNIX 进程
- 08.2 flag 包
- 8.2 flag 包
- 08.3 io.Reader 和 io.Writer 接口
- 08.4 bufio 包
- 08.5 读取文本文件
- 08.6 从文件中读取所需的数据量
- 08.7 为什么我们使用二进制格式
- 08.8 读取 CSV 文件
- 08.9 写入文件
- 08.10 从磁盘加载和保存数据
- 08.11 再看strings包
- 08.12 关于bytes包
- 08.13 文件权限
- 08.14 处理 Unix 信号
- 08.15 Unix 管道编程
- 08.16 遍历目录树
- 08.17 使用 ePBF
- 08.18 关于 syscall.PtraceRegs
- 08.19 跟踪系统调用
- 08.20 User ID 和 group ID
- 08.21 其他资源
- 08.22 练习
- 08.23 总结
- 9 并发 Goroutines、Channel 和 Pipeline
- 10 Go 并发-进阶讨论
- 11 代码测试、优化及分析
- 12 Go 网络编程基础
- 13 网络编程 - 构建服务器与客户端
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
10.5.1 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 同时去修改共享变量,这也是随机输出的主要原因。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论