Go by Example: Mutexes 互斥锁

本文介绍了在Go语言中如何使用互斥锁(Mutex)确保并发环境下计数器状态的安全更新,以及如何通过协程和通道来实现相同的目标。示例代码展示了在多协程访问共享数据时,互斥锁如何提供同步,并演示了一个简单的并发计数器实现。

英文源地址
在之前的示例中, 我们看到了如何使用原子操作来管理简单的计数器状态. 对于复杂的状态, 我们可以使用互斥锁跨多个协程安全地访问数据.

package main

import (
	"fmt"
	"sync"
)

// Container 存放计数器地映射: 因为我们想从多个协程并发地更新它
// 所以我们添加了一个互斥锁来同步访问
// 注意, 互斥锁不能被复制.所以如果传递这个结构体, 应该通过指针来完成.
type Container struct {
	mu       sync.Mutex
	counters map[string]int
}

// 在访问计数器前锁定互斥锁, 在函数末尾使用defer语句解锁它
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

	// 这个函数在循环中增加一个命名的计数器
	doIncrement := func(name string, n int) {
		for i := 0; i < n; i++ {
			c.inc(name)
		}
		wg.Done()
	}

	// 并发运行多个协程时注意, 它们都访问同一个container, 其中两个访问同一个计时器
	wg.Add(3)
	go doIncrement("a", 10000)
	go doIncrement("a", 10000)
	go doIncrement("b", 10000)

	// 等待协程运行完成
	wg.Wait()
	fmt.Println(c.counters)
}

运行程序显示计数器按预期进行了更新.

$ go run mutexes.go
map[a:20000 b:10000]

接下来, 我们将研究如何仅仅使用协程和通道来实现相同的状态管理任务.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值