在前面的例子中,我们看到了如何使用原子操作(atomic-counters)来管理简单的计数器。 对于更加复杂的情况,我们可以使用一个互斥量 来在 Go 协程间安全的访问数据。 |
|
package main |
|
import ( "fmt" "sync" ) |
|
Container 中定义了 counters 的 map ,由于我们希望从多个 goroutine 同时更新它,
因此我们添加了一个 互斥锁Mutex 来同步访问。
请注意不能复制互斥锁,如果需要传递这个 |
type Container struct { mu sync.Mutex counters map[string]int } |
在访问 |
func (c *Container) inc(name string) { |
c.mu.Lock() defer c.mu.Unlock() c.counters[name]++ } |
|
请注意,互斥量的零值是可用的,因此这里不需要初始化。 |
func main() { c := Container{ |
counters: map[string]int{"a": 0, "b": 0}, } |
|
var wg sync.WaitGroup |
|
这个函数在循环中递增对 name 的计数 |
doIncrement := func(name string, n int) { for i := 0; i < n; i++ { c.inc(name) } wg.Done() } |
同时运行多个 goroutines;
请注意,它们都访问相同的 |
wg.Add(3) go doIncrement("a", 10000) go doIncrement("a", 10000) go doIncrement("b", 10000) |
等待上面的 goroutines 都执行结束 |
wg.Wait() fmt.Println(c.counters) } |
运行这个程序显示计数器更新和我们期望的一致 |
$ go run mutexes.go map[a:20000 b:10000] |
接下来我们将看一下,只使用协程和通道, 如何实现相同的任务状态管理。 |
下一个例子: 状态协程