英文:
Printing map object when it is locked by mutex
问题
我不确定为什么互斥锁(mutex)没有按照我预期的方式工作。任何建议都会对我有所帮助。
这是我的代码:
package main
import (
"fmt"
"sync"
"time"
)
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]++
// fmt.Println("in", name, c.counters)
// 这个打印语句在 goroutine 之间产生了问题
time.Sleep(time.Second)
}
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)
fmt.Println(name, c.counters)
}
wg.Done()
}
wg.Add(3)
go doIncrement("a", 2)
go doIncrement("b", 2)
go doIncrement("a", 2)
wg.Wait()
fmt.Println(c.counters)
}
当我运行这段代码时,我得到了奇怪的输出:
a map[a:2 b:0]
a map[a:2 b:0]
b map[a:2 b:1]
a map[a:4 b:1]
a map[a:4 b:1]
b map[a:4 b:2]
map[a:4 b:2]
我期望能够看到一些日志,其中可以看到 a
增加到 1、2、3、4。
当我移除 inc
函数中的注释时,我可以看到预期的日志:
in a map[a:1 b:0]
a map[a:1 b:0]
in a map[a:2 b:0]
a map[a:2 b:0]
in b map[a:2 b:1]
b map[a:2 b:1]
in a map[a:3 b:1]
a map[a:3 b:1]
in a map[a:4 b:1]
a map[a:4 b:1]
in b map[a:4 b:2]
b map[a:4 b:2]
map[a:4 b:2]
请问有什么问题导致互斥锁没有按照预期工作?
英文:
I am not sure why mutex is not working as I expected. Any advice will help me.
Here is my code.
package main
import (
"fmt"
"sync"
"time"
)
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]++
// fmt.Println("in", name, c.counters)
// This print is doing tricks between goroutines
time.Sleep(time.Second)
}
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)
fmt.Println(name, c.counters)
}
wg.Done()
}
wg.Add(3)
go doIncrement("a", 2)
go doIncrement("b", 2)
go doIncrement("a", 2)
wg.Wait()
fmt.Println(c.counters)
}
When I ran this, I got strange outputs.
a map[a:2 b:0]
a map[a:2 b:0]
b map[a:2 b:1]
a map[a:4 b:1]
a map[a:4 b:1]
b map[a:4 b:2]
map[a:4 b:2]
I expected some logs where I can see a
increased to 1,2,3,4
When I removed comments in inc
function;
I could see the expected logs.
in a map[a:1 b:0]
a map[a:1 b:0]
in a map[a:2 b:0]
a map[a:2 b:0]
in b map[a:2 b:1]
b map[a:2 b:1]
in a map[a:3 b:1]
a map[a:3 b:1]
in a map[a:4 b:1]
a map[a:4 b:1]
in b map[a:4 b:2]
b map[a:4 b:2]
map[a:4 b:2]
答案1
得分: 3
在这个循环中:
for i := 0; i < n; i++ {
c.inc(name) // 这个在互斥锁被锁定时运行
fmt.Println(name, c.counters) // 这个在互斥锁未锁定时运行
}
Println 在互斥锁保护的区域之外运行。两个 goroutine 同时尝试增加 "a",一个增加后等待。当该增加函数返回时,第二个函数进入并增加,然后第一个函数的 Println 运行,然后第二个函数的 Println 打印相同的内容。
所以,互斥锁按预期工作,但你在互斥锁保护的区域之外进行了打印。
英文:
In this loop:
for i := 0; i < n; i++ {
c.inc(name) ---> This runs with mutex locked
fmt.Println(name, c.counters) --> This runs with mutex unlocked
}
The Println runs outside the mutex lock. Two goroutines attempt to increment "a" at the same time, one increments and then waits. When that increment function returns, the second one goes in and increments, then Println from the first one runs, then Println from the second one prints the same thing.
So, mutex is working as expected, but you are printing outside the region protected by mutex.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论