【发布时间】:2020-11-06 09:51:11
【问题描述】:
下面是我在学习 Golang 中的 goroutine 时正在研究的一个示例。在下面的代码中,我们生成了 30 个 goroutine,每个 goroutine 都访问一个名为 ordersProcessed 的共享变量。该示例代表一个收银员处理订单。一旦 ordersProcessed 超过 10,我们就会打印出收银员无法再接单。
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var (
wg sync.WaitGroup
ordersProcessed int64
)
// This does not work as expected
cashier := func(orderNum int) {
value := atomic.LoadInt64(&ordersProcessed)
fmt.Println("Value is ", value)
if value < 10 {
// Cashier is ready to serve!
fmt.Println("Proessing order", orderNum)
atomic.AddInt64(&ordersProcessed, 1)
} else {
// Cashier has reached the max capacity of processing orders.
fmt.Println("I am tired! I want to take rest!", orderNum)
}
wg.Done()
}
for i := 0; i < 30; i++ {
wg.Add(1)
go func(orderNum int) {
// Making an order
cashier(orderNum)
}(i)
}
wg.Wait()
}
我希望看到 10 个订单的已处理消息,并且以后无法处理。但是,所有 30 个订单都会得到处理。我使用了 sync/atomic 包来同步对 ordersProcessed 变量的访问,但是它的值总是被每个 goroutine 读取为 0。但是,如果我将上面的代码更改为使用下面的互斥锁,它会按预期工作:
package main
import (
"fmt"
"sync"
)
func main() {
var (
wg sync.WaitGroup
ordersProcessed int64
mutex sync.Mutex
)
// This works as expected
cashier := func(orderNum int) {
mutex.Lock()
if ordersProcessed < 10 {
// Cashier is ready to serve!
fmt.Println("Processing order", orderNum)
ordersProcessed++
} else {
// Cashier has reached the max capacity of processing orders.
fmt.Println("I am tired! I want to take rest!", orderNum)
}
mutex.Unlock()
wg.Done()
}
for i := 0; i < 30; i++ {
wg.Add(1)
go func(orderNum int) {
// Making an order
cashier(orderNum)
}(i)
}
wg.Wait()
}
谁能告诉我我使用 sync/atomic 包同步对 ordersProcessed 变量的访问的方式有什么问题?
【问题讨论】:
标签: go synchronization goroutine