golang下面代码为什么会死锁

发布于 2022-09-12 00:06:42 字数 1371 浏览 16 评论 0


type UserTable struct {
    sync.RWMutex
    //deadlock.RWMutex

    table map[int]string
}

func NewUserTable()*UserTable{
    return &UserTable{
        table:make(map[int]string),
    }
}

func (userTable *UserTable)GetUser(i int)string{
    userTable.RLock()
    defer userTable.RUnlock()
    if name, exist := userTable.table[i]; exist{
        return name
    }
    return ""
}

func (userTable *UserTable)GetTable()map[int]string{
    userTable.RLock()
    defer userTable.RUnlock()
    newMap := make(map[int]string)
    for seatID, _ := range userTable.table{
        newMap[seatID] = userTable.GetUser(seatID)
    }
    return newMap
}

func (userTable *UserTable)SetUser(i int, name string){
    userTable.Lock()
    defer userTable.Unlock()
    if len(userTable.table) >= 100{
        userTable.table = make(map[int]string)
    }
    userTable.table[i] = name
}


func main() {
    userTable := NewUserTable()
    go func() {
        i := 0
        for{
            if i % 1000 == 0{
                fmt.Printf("%v\n", userTable.GetTable())
            }
            userTable.SetUser(i, fmt.Sprintf("%v", i))
            i++
        }

    }()

    go func(){
        for{
            userTable.GetTable()
            time.Sleep(100*time.Millisecond)
        }

    }()
    select {

    }
    //time.Sleep(100* time.Second)
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白云不回头 2022-09-19 00:06:42

问题在于 GetTable 方法:在该方法中你已经加锁来保护 table 中的数据了,直接操作数据就行了,不应该画蛇添足地调用 GetUser 方法,因为 GetUser 中也要加锁

结果就导致,在第二个 go func 中 GetTable 的两次 RLock 之间,第一个 go func 中的 SetUser 进行 RWLock,此时就会死锁


解决方法很简单,在 GetTable 中直接操作 table,不要再去调用 GetUser 了,

如果从 table 获取值的操作确实在 GetUser 和 GetTable 中都存在,并且较为复杂,你可以再写一个 非导出 的 _help 方法来实现这个功能,这个方法里不要加锁,然后 GetUser 和 GetTable 都调用这个函数

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文