Golang垃圾收集器和地图

Golang垃圾收集器和地图,go,garbage-collection,maps,Go,Garbage Collection,Maps,我正在处理goroutine中的一些用户会话数据,并创建一个映射来跟踪其中的用户id->会话数据。goroutine在一个切片中循环,如果找到SessionEnd事件,映射键将在同一迭代中删除。这似乎并不总是如此,因为我仍然可以在接下来的迭代中检索一些数据以及“key exists”bool变量。好像有些变量还没有归零 每个地图只有一个从中写入/读取的goroutine。从我的理解来看,不应该存在竞争条件,但map和delete()显然存在竞争条件 如果垃圾收集器在每次迭代中都运行,那么代码可以

我正在处理goroutine中的一些用户会话数据,并创建一个映射来跟踪其中的用户id->会话数据。goroutine在一个切片中循环,如果找到SessionEnd事件,映射键将在同一迭代中删除。这似乎并不总是如此,因为我仍然可以在接下来的迭代中检索一些数据以及“key exists”bool变量。好像有些变量还没有归零

每个地图只有一个从中写入/读取的goroutine。从我的理解来看,不应该存在竞争条件,但map和delete()显然存在竞争条件

如果垃圾收集器在每次迭代中都运行,那么代码可以正常工作。我使用地图的目的不对吗

伪代码(在单个goroutine中运行的函数,行作为变量传递):

active:=make(ActiveSessions)//map[int]UserSession
对于u,l:=范围行{//lines是已解析日志的一个片段
u=l.EventData.(parser.User)
s、 存在=活动[u.SessionID]
开关l.事件{
//包含可以检查是否存在正确或错误的案例
//错误如果包含无法发生的事件,
//例如,UserConnect之前的UserDisconnect,
//或在会话已处于活动状态时使用UserConnect
案例“UserConnect”:
如果存在{
//错误,无法发生
//前一个会话完成后,日志中可能会出现相同的会话id,
//这正是问题发生的时间
}        
案例“UserDisconnect”:
sessionFinished=true
}
// ...
如果会话已完成{
// 
删除(活动,u.SessionID)
//只有在此处执行runtime.GC()时,代码才能工作,这可能只是巧合
}
}

我看不出你所做的有什么不对。当您调用
delete
时,该条目将从映射中删除,因此在以后的迭代中不会看到它。您不需要手动运行垃圾回收器来实现这一点。你能提供一个最小的、完整的、可验证的例子来说明这个问题吗?据我所知,一个映射包含一个内部变量,它定义一个键是否存在以及它使用的内存是否可以重复使用。我试图在一个小应用程序中复制这个,但失败了。@hiqluid:您正在搜索没有魔法的地方。如果数据仍然可以在地图中访问,那不是因为缺少垃圾收集。你用种族检测器测试过你的代码吗?否则,我们需要一个更完整的示例来重现该问题。在每个循环迭代开始时,您似乎没有将
sessionFinished
变量重新初始化为
false
active := make(ActiveSessions) // map[int]UserSession

for _, l := range lines { // lines is a slice of a parsed log
    u = l.EventData.(parser.User)
    s, exists = active[u.SessionID]

    switch l.Event {
    // Contains cases which can check if exists is true or false
    // errors if contains an event that can't happen, 
    // for example UserDisconnect before UserConnect,
    // or UserConnect while a session is already active

    case "UserConnect":
        if exists {
            // error, can't occur

            // The same session id can occur in the log after a prior session has completed,
            // which is exactly when the problems occur
        }        

    case "UserDisconnect":
        sessionFinished = true

    }

    // ...

    if sessionFinished {
        // <add session to finished sessions>

        delete(active, u.SessionID)

        // Code works only if runtime.GC() is executed here, could just be a coincidence
    }
}