Golang:对于一个具有只读访问权限的包级变量,是否需要使用互斥锁?

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

Golang: is a mutex required for a package-scoped variable with read-only access?

问题

如果我有一个像这样的包作用域变量:

var (
    bus *Bus // 这个变量
)

// Bus 表示一个仓库总线。它包含所有的仓库。
type Bus struct {
    UserRepository *UserRepository
    // ...
}

...并且我在我的仓库中给予对 bus 变量的访问权限,以便它们可以相互访问,那么如果它们可以并发使用,我需要使用任何类型的互斥锁吗?

以下是大致的伪代码:

// 路由器
router.GET("/user/:id", c.FindUser)

// 控制器
func (c *UserController) FindUser(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte(c.UserService.FindUser(r.Get("id"))))
}

// 服务
func (s UserService) FindUser(id int) *domain.User {
    return s.UserRepository.FindByID(id) 
}

// 仓库
func (r UserRepository) FindByID(id int) *domain.User {
    // 这是包作用域的 `bus` 变量将被使用的地方
}

FindByID 函数中,我可能会使用包作用域的 bus 变量,当然它可以被并发访问,因为它将在每个 HTTP 请求触发时被调用,而这些请求都是并发处理的。

英文:

If I have a package-scoped variable like this:

var (
	bus *Bus // THIS VARIABLE
)

// Bus represents a repository bus. This contains all of the repositories.
type Bus struct {
	UserRepository *UserRepository
    // ...
}

...and I give access to the bus variable on my repositories so that they can access each other, do I need to use any sort of mutex if they can be used concurrently?

Quick pseudocode of what would happen:

// Router
router.GET("/user/:id", c.FindUser)

// Controller
func (c *UserController) FindUser(w http.ResponesWriter, r *http.Request) {
    w.Write([]byte(c.UserService.FindUser(r.Get("id"))))
}

// Service
func (s UserService) FindUser(id int) *domain.User {
    return s.UserRepository.FindByID(id) 
}

// Repository
func (r UserRepository) FindByID(id int) *domain.User {
    // This is where the package-scope `bus` variable will be used
}

In the FindByID function, I may use the package-scoped bus variable, which of course can be accessed concurrently since it will be called whenever an HTTP request triggers it, and those are all handled concurrently.

答案1

得分: 6

如果你只是读取变量的内容,那么不,你不需要互斥锁。然而,如果你要改变它的状态,那么你需要保护它。

两个并发的写操作或者并发的写和读操作可能会导致问题。如果你的写操作很少,你可以考虑使用RWMutex。它允许多个读操作同时进行,但不允许与写操作同时进行。

另外,你可以查看竞争检测器。它是尽力而为的检测器,不能保证你没有竞争条件,但可以检测出一些情况。还要注意,你需要引发竞争条件才能让竞争检测器检测到,所以需要编写使用bus并发访问的测试或模拟真实条件。

英文:

If all you do is reading the content of variable - then no, you do not need mutex. However, if you ever mutate its state, then you need to protect it.

Two concurrent writes or concurrent write and read can cause problems. If your writes are rare, you might want to use RWMutex. It will allow multiple readers to access, but not together with a writer.

Also, check out race detector. It is best effort detector, so it does not guarantee that you do not have race condition, but it can detect some use cases. Also note that you need to cause race in order for race detector to detect it, so writing tests that use your bus concurrently or simulating real conditions has to be done.

huangapple
  • 本文由 发表于 2017年8月5日 05:34:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/45515809.html
匿名

发表评论

匿名网友

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

确定