- 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原子计数器实例
Go语言中管理状态的主要机制是通过通道进行通信。在过去的文章中我们已经看到了这一点,例如工人池。 还有一些其他选项用于管理状态。 这里我们将使用sync/atomic
包来实现由多个goroutine
访问的原子计数器。
使用一个无符号整数表示计数器(正数)。
为了模拟并发更新,将启动50
个goroutine
,每个增量计数器大约是1
毫秒。
为了原子地递增计数器,这里使用AddUint64()
函数,在ops
计数器的内存地址上使用&
语法。
在增量之间等待一秒,允许一些操作累积。
为了安全地使用计数器,同时它仍然被其他goroutine
更新,通过LoadUint64
提取一个当前值的副本到opsFinal
。 如上所述,需要将获取值的内存地址&ops
给这个函数。
运行程序显示执行了大约40,000
次操作。
所有的示例代码,都放在
F:\worksp\golang
目录下。安装Go编程环境请参考:/tutorial/detail-5562.html
atomic-counters.go
的完整代码如下所示 -
package main import "fmt" import "time" import "sync/atomic" func main() { // We'll use an unsigned integer to represent our // (always-positive) counter. var ops uint64 = 0 // To simulate concurrent updates, we'll start 50 // goroutines that each increment the counter about // once a millisecond. for i := 0; i < 50; i++ { go func() { for { // To atomically increment the counter we // use `AddUint64`, giving it the memory // address of our `ops` counter with the // `&` syntax. atomic.AddUint64(&ops, 1) // Wait a bit between increments. time.Sleep(time.Millisecond) } }() } // Wait a second to allow some ops to accumulate. time.Sleep(time.Second) // In order to safely use the counter while it's still // being updated by other goroutines, we extract a // copy of the current value into `opsFinal` via // `LoadUint64`. As above we need to give this // function the memory address `&ops` from which to // fetch the value. opsFinal := atomic.LoadUint64(&ops) fmt.Println("ops:", opsFinal) }
执行上面代码,将得到以下输出结果 -
F:\worksp\golang>go run atomic-counters.go ops: 41360