互斥锁未锁定

huangapple go评论62阅读模式
英文:

Mutex not locking

问题

我注意到在使用 Mutex 时出现了一些意外的行为,所以我决定编写一些测试代码。

package main

import (
	"fmt"
	"sync"
)

type Box struct {
	Stuff int
	mu    sync.Mutex
}

var box Box

func init() {
	box = Box{}
	box.mu.Lock()
}

func (box *Box) add() {
	fmt.Println("add()")
	box.mu.Unlock()
	box.Stuff++
	box.mu.Lock()
}

func (box *Box) display() {
	fmt.Print("display(): ")
	box.mu.Unlock()
	fmt.Println(box.Stuff)
	box.mu.Lock()
}

func add2() {
	fmt.Println("add2()")
	box.Stuff++ // 增加了,但不应该增加,预期出错
}

func display2() {
	fmt.Print("display2(): ")
	fmt.Println(box.Stuff) // 显示了,但不应该显示,预期出错
}

func main() {
	box.display()
	box.add()
	box.display()
	display2()
	add2()
	box.display()
}

没有使用指针接收器的函数可以添加和访问受保护的结构体。
运行代码。

display(): 0
add()
display(): 1
display2(): 1
add2()
display(): 2

我原本期望那两个带有附加名称 "2" 的函数会失败。
但它们没有失败。

有什么想法吗?

英文:

I noticed some unexpected behavior when using Mutex so I decided to write some test code.

package main

import (
	"fmt"
	"sync"
)

type Box struct {
	Stuff int
	mu    sync.Mutex
}

var box Box

func init() {
	box = Box{}
	box.mu.Lock()
}

func (box *Box) add() {
	fmt.Println("add()")
	box.mu.Unlock()
	box.Stuff++
	box.mu.Lock()
}

func (box *Box) display() {
	fmt.Print("display(): ")
	box.mu.Unlock()
	fmt.Println(box.Stuff)
	box.mu.Lock()
}

func add2() {
	fmt.Println("add2()")
	box.Stuff++ //increments but should not, error expected
}

func display2() {
	fmt.Print("display2(): ")
	fmt.Println(box.Stuff) //displays but should not, error expected
}

func main() {
	box.display()
	box.add()
	box.display()
	display2()
	add2()
	box.display()
}

The functions without pointer receivers can add & access the protected struct.
Running the code.

display(): 0
add()
display(): 1
display2(): 1
add2()
display(): 2

I would expect the two functions which have the name appended with a 2 to fail.
They do not.

Any idea?

答案1

得分: 3

你可能想以稍微不同的方式编写这段代码:

你可以通过加锁来开始,这不是使用锁的最常见方式:除非解锁,否则一切都被锁住。

更常见的方式是:

package main

import (
    "fmt"
    "sync"
)

type Box struct {
    Stuff int
    mu    sync.Mutex
}

var box Box

func init() {
    box = Box{}
}

func (box *Box) add() {
    fmt.Println("add()")
    box.mu.Lock()
    box.Stuff++
    box.mu.Unlock()
}
...

将锁的作用范围限定在变化的时刻,而不是整个应用程序。

英文:

You might want to write this a bit different:

You start by locking, which is not the most common way to use a lock: Everything is locked unless you unlock it.

A more common way is:

package main

import (
    "fmt"
    "sync"
)

type Box struct {
    Stuff int
    mu    sync.Mutex
}

var box Box

func init() {
    box = Box{}
}

func (box *Box) add() {
    fmt.Println("add()")
    box.mu.Lock()
    box.Stuff++
    box.mu.Unlock()
}
...

Scoping your locks to the moment of change and not to the complete app.

huangapple
  • 本文由 发表于 2022年7月23日 05:50:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/73086397.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定