如何在更改地图数据时防止死锁

时间:2014-09-09 13:02:48

标签: multithreading go

我尝试编写一个验证数据的函数。请查看以下代码:

func Create(name, email, password, local string, termOf bool) map[string]string {

    wait := new(sync.WaitGroup)
    mutex := new(sync.Mutex)
    errMsg := make(map[string]string)

    if !termOf {
        mutex.Lock()
        errMsg["termOf"] = translate(local, "text06")
        mutex.Unlock()
    }

    wait.Add(1)
    go func() {
        err := ValidateName(name, local)
        mutex.Lock()
        errMsg["name"] = err.Error()
        mutex.Unlock()
        wait.Done()
    }()

    wait.Add(1)
    go func() {
        err := ValidateEmail(email, local)
        mutex.Lock()
        errMsg["email"] = err.Error()
        mutex.Unlock()
        wait.Done()
    }()

    wait.Add(1)
    go func() {
        err := ValidatePassword(password, local)
        mutex.Lock()
        errMsg["password"] = err.Error()
        mutex.Unlock()
        wait.Done()
    }()

    wait.Wait()

    // If errors appear
    if len(errMsg) > 0 {
        return errMsg
    }

    return nil
}

正如你在这里看到的,我使用了三个goroutine,在goroutine中我锁定它来改变errMsg变量的地图类型。当我运行该函数时,我遇到了编译器错误

runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x14 pc=0x44206a]

但是当我在goroutine中删除所有errMsg插入时,该函数才有效。我不知道我做错了什么。

1 个答案:

答案 0 :(得分:3)

errnilValidateName()来电回复时,ValidateEmail()可能是ValidatePassword()

在将err != nil添加到地图之前,您应先检查一下。

if err != nil {
    mutex.Lock()
    errMsg["xxx"] = err.Error()
    mutex.Unlock()
}

换句话说,这不是问题所在的地图errMsg,而是您想要加入的地图。