简体   繁体   English

Golang MGO模块是否锁定或解锁Go对象?

[英]Does the Golang MGO module lock or unlock Go objects?

I am trying to understand whether Mongo locks Go objects. 我试图了解Mongo是否锁定Go对象。

The first function works fine with the json encoder, however the second function fails fatal error: sync: Unlock of unlocked RWMutex . 第一个功能可与json编码器正常工作,但是第二个功能可fatal error: sync: Unlock of unlocked RWMutex Is this because mongo.Find is already trying to lock/unlock the state object? 这是因为mongo.Find已经在尝试锁定/解锁状态对象吗? Do I need to externally handle race competition for my go objects or does MGO take care of it? 我需要从外部处理围棋比赛还是MGO照顾呢? I tried reading the source code but I haven't been able to reach a conclusion. 我尝试阅读源代码,但无法得出结论。

Any would be much appreciated! 任何将不胜感激!

import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"io"
"sync"
"encoding/json"
)

type ApplicationState struct {
    FileStates map[string]FileState     `json:"fileStates" bson:"fileStates"` 
    lock       sync.RWMutex             `json:"-" bson:"-"`
}

func (state *ApplicationState) ReadState(reader io.Reader) error {
    state.lock.Lock()
    defer state.lock.Unlock()
    return json.NewDecoder(reader).Decode(state)}

func (state *ApplicationState) ReadStateMGO(c *mgo.Collection) error {
    state.lock.Lock()
    defer state.lock.Unlock()
    return c.Find( bson.M{} ).Select( bson.M{"_id": 0} ).One(state)}

Note: to test it you can just replace the Filestate field with a string map. 注意:要测试它,您只需将Filestate字段替换为字符串映射即可。

First, drop gopkg.in/mgo.v2 , it's obsolte, unmaintained. 首先,删除gopkg.in/mgo.v2 ,此文件已过时,无需维护。 Instead use the community supported fork: github.com/globalsign/mgo . 而是使用社区支持的fork: github.com/globalsign/mgo

Next, you should first read the public, package documentation, and only "revert" to reading the source to clear such things up if the documentation does not offer the answers. 接下来,您应该首先阅读公共的,打包的文档,并且如果文档没有提供答案,则只能“还原”阅读源以清除此类内容。 But drawing conclusions from the source is always dangerous, as the implementation may change at any time, only what is documented is guaranteed. 但是从源头得出结论总是很危险的,因为实现可能随时更改,因此只能保证所记录的内容。 Documentation of mgo.Session states: mgo.Session文档指出:

All Session methods are concurrency-safe and may be called from multiple goroutines. 所有Session方法都是并发安全的,可以从多个goroutine中调用。

This is all the guarantee you have, and all you should depend on. 这是您所拥有的所有保证,也是您应依靠的所有保证。 Using methods of mgo.Collection may or may not be safe for concurrent use, so do not do that. 使用mgo.Collection方法可以安全使用,也可以不安全,因此不要这样做。 When needed, always obtain a "new" collection from the session, as that is safe to be accessed from multiple goroutines. 必要时,请始终从会话中获取“新”集合,因为可以从多个goroutine中安全地访问该集合。

And now on to your actual problem. 现在到您的实际问题。

Your ApplicationState struct type contains a lock ( sync.RWMutex ), and you unmarshal your query result into the same ApplicationState value that holds the lock: 您的ApplicationState结构类型包含一个锁( sync.RWMutex ),并且您将查询结果解组为与持有该锁相同的ApplicationState值:

func (state *ApplicationState) ReadStateMGO(c *mgo.Collection) error {
    state.lock.Lock()
    defer state.lock.Unlock()
    return c.Find( bson.M{} ).Select( bson.M{"_id": 0} ).One(state)
}

This is a red flag! 这是一个危险信号! Don't do this! 不要这样! Unmarshaling into a value may clear any fields, including the lock! 取消编组为一个值可能会清除所有字段,包括锁!

Yes, you may say it's an unexported field, so the mgo package should not / could not change it. 是的,您可能会说这是未导出的字段,因此mgo软件包不应/不能更改它。 This is true, but the mgo package may decide to create a new ApplicationState value to unmarshal into, and the new value may be assigned to the value pointed by the passed pointer ( state ). 的确如此,但是mgo包可能会决定创建一个新的ApplicationState值以将其编组到其中,并且可以将新值分配给所传递的指针( state )指向的值。

If this happens, the newly created ApplicationState will have a lock field being its zero-value, which is an unlocked mutex. 如果发生这种情况,新创建的ApplicationState将具有一个lock字段,该lock字段的值为零,这是一个未锁定的互斥锁。 And once this happens, the subsequent unlock will obviously fail (panic). 一旦发生这种情况,随后的解锁显然会失败(紧急)。

Solution? 解? Move locks outside of struct values you intend to serialize / deserialize. 将锁移到要序列化/反序列化的结构值之外。 Or at least don't expect the lock state to transfer along with other fields. 或者至少不要期望锁状态与其他字段一起转移。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM