- Go语言入门
- Go语言开发环境安装配置
- Go语言程序结构
- Go语言基础语法
- Go语言数据类型
- Go语言变量
- Go语言常量
- Go语言运算符
- Go语言条件和决策
- Go语言循环
- Go语言函数
- Go语言作用域规则
- Go语言字符串
- Go语言数组
- Go语言指针
- Go语言结构体
- Go语言切片
- Go语言范围(range)
- Go语言映射
- Go语言递归
- Go语言类型转换
- Go语言接口
- Go语言错误处理
-
Go编程代码实例
- Hello World程序实例
- Go变量实例
- Go常量实例
- Go for循环语句实例
- Go if/else语句实例
- Go switch语句实例
- Go切片实例
- Go范围实例
- Go函数实例
- Go函数多个返回值实例
- Go可变参数的函数实例
- Go闭包(匿名函数)实例
- Go函数递归实例
- Go指针实例
- Go指针实例
- Go接口实例
- Go错误实例
- Go程序实例
- Go通道实例
- Go通道缓冲实例
- Go通道同步实例
- Go通道路线实例
- Go Select实例
- Go超时(timeouts)实例
- Go非阻塞通道操作实例
- Go关闭通道实例
- Go通道范围实例
- Go计时器实例
- Go断续器实例
- Go工作池实例
- Go速率限制实例
- Go原子计数器实例
- Go互斥体实例
- Go有状态的goroutines实例
- Go排序实例
- Go按自定义函数排序实例
- Go panic错误处理实例
- Go延迟(defer)实例
- Go集合函数实例
- Go字符串函数实例
- Go字符串格式化实例
- Go正则表达式实例
- Go JSON实例
- Go时间日期实例
- Go时代(Epoch)实例
- Go时间格式化/解析实例
- Go随机数实例
- Go数字解析实例
- Go URL解析实例
- Go SHA1哈希实例
- Go Base64编码实例
- Go读取文件实例
- Go写文件实例
- Go行过滤器实例
- Go命令行参数实例
- Go命令行标志实例
- Go环境变量实例
- Go执行过程实例
- Go信号实例
- Go退出程序实例
Go互斥体实例
在前面的例子中,我们看到了如何使用原子操作来管理简单的计数器状态。对于更复杂的状态,可以使用互斥体来安全地访问多个goroutine
中的数据。
在这个例子中,状态(state)是一个映射。
示例中的互斥将同步访问状态。
我们将跟踪执行的读写操作的数量。
这里将启动100
个goroutine
来对状态执行重复读取,每个goroutine
中每毫秒读取一次。
对于每个读取,我们选择一个键来访问,Lock()
互斥体以确保对状态的独占访问,读取所选键的值,Unlock()
互斥体,并增加readOps
计数。
我们还将启动10
个goroutine
来模拟写入,使用与读取相同的模式。
让10
个goroutine
在状态和互斥体上工作一秒钟。采集和报告最终操作计数。
收集和报告最终操作计数。用最后的锁状态,显示它是如何结束的。
运行程序显示,我们对互斥同步状态执行了大约90,000
次的操作。
所有的示例代码,都放在
F:\worksp\golang
目录下。安装Go编程环境请参考:/tutorial/detail-5562.html
mutexes.go
的完整代码如下所示 -
package main import ( "fmt" "math/rand" "sync" "sync/atomic" "time" ) func main() { // For our example the `state` will be a map. var state = make(map[int]int) // This `mutex` will synchronize access to `state`. var mutex = &sync.Mutex{} // We'll keep track of how many read and write // operations we do. var readOps uint64 = 0 var writeOps uint64 = 0 // Here we start 100 goroutines to execute repeated // reads against the state, once per millisecond in // each goroutine. for r := 0; r < 100; r++ { go func() { total := 0 for { // For each read we pick a key to access, // `Lock()` the `mutex` to ensure // exclusive access to the `state`, read // the value at the chosen key, // `Unlock()` the mutex, and increment // the `readOps` count. key := rand.Intn(5) mutex.Lock() total += state[key] mutex.Unlock() atomic.AddUint64(&readOps, 1) // Wait a bit between reads. time.Sleep(time.Millisecond) } }() } // We'll also start 10 goroutines to simulate writes, // using the same pattern we did for reads. for w := 0; w < 10; w++ { go func() { for { key := rand.Intn(5) val := rand.Intn(100) mutex.Lock() state[key] = val mutex.Unlock() atomic.AddUint64(&writeOps, 1) time.Sleep(time.Millisecond) } }() } // Let the 10 goroutines work on the `state` and // `mutex` for a second. time.Sleep(time.Second) // Take and report final operation counts. readOpsFinal := atomic.LoadUint64(&readOps) fmt.Println("readOps:", readOpsFinal) writeOpsFinal := atomic.LoadUint64(&writeOps) fmt.Println("writeOps:", writeOpsFinal) // With a final lock of `state`, show how it ended up. mutex.Lock() fmt.Println("state:", state) mutex.Unlock() }
执行上面代码,将得到以下输出结果 -
F:\worksp\golang>go run mutexes.go readOps: 84546 writeOps: 8473 state: map[0:99 3:3 4:62 1:18 2:89]
上一篇:Go原子计数器实例