golang互斥锁的君子协定
时间:2018-12-20 09:53:43 +0800 CST 浏览:999

golang中的互斥锁并不能锁定任何内存或代码或变量。

golang_S1-l6gVIX.jpg

问题测试

代码

package main

import (
    "fmt"
    "sync"
    "time"
)

var wg sync.WaitGroup
var name = "hello world"
var mu sync.Mutex

func main() {
    wg.Add(1)
    go modify()

    time.Sleep(1 * time.Second)
    name = "dddddd" //有锁应该修改失败或者阻塞
    fmt.Println("in main", name)

    wg.Wait()
}

func modify() {
    defer wg.Done()
    mu.Lock()
    defer mu.Unlock()

    name = "modify"
    time.Sleep(2 * time.Second)
    fmt.Println("in modify", name)
}

结果

in main dddddd
in modify dddddd

问题说明

main函数里成功修改,意味着Lock并不能保护任何内存或变量,不使用锁的代码仍然可以随便操作。

go的mutex只是一个君子协定:在有可能造成race
condition的地方,通过判断状态(是否已Lock)来决定能否操作。而非强制性保护。即:Lock()之前先通过状态判断是否为“可以操作”,如果可以就修改状态,保证其他goroutine查询状态的结果是“不可操作,需等待”。修改完成后将状态改为“可以操作”,后续gouroutine才能接手。

所以必须在所有可能造成race condition的代码处加上Lock,保证其遵守君子约定,否则这段代码就会是一个“野蛮人”可以随意操作了。

解决方法

代码

package main

import (
    "fmt"
    "sync"
    "time"
)

var wg sync.WaitGroup

func main() {
    // object锁
    wg.Add(1)
    t := new(test)
    go t.modify()

    time.Sleep(1 * time.Second)

    t.Lock()
    defer t.Unlock()
    t.name = "dddddd" //有锁应该修改失败或者阻塞
    fmt.Println("in main", t.name)

    wg.Wait()
}

type test struct {
    sync.Mutex
    name string
}

func (t *test) modify() {
    defer wg.Done()
    t.Lock()
    defer t.Unlock()
    t.name = "modify"
    time.Sleep(2 * time.Second)
    fmt.Println("in modify", t.name)
}

结果

in modify modify
in main dddddd


如果这篇文章对你有所帮助,可以通过下边的“打赏”功能进行小额的打赏。

本网站部分内容来源于互联网,如有侵犯版权请来信告知,我们将立即处理。


来说两句吧