首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
beego
V2EX  ›  Go

关于 golang 互斥锁的一个疑问

  •  
  •   gramyang · 100 天前 · 1297 次点击
    这是一个创建于 100 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码见 https://github.com/GramYang/GoTest/blob/master/sync/mutex1.go

    第一个 test 输出的是小于 1000 的随机值。 第二个 test 稳定输出 1000,但是限制了原生线程的数量,这在工作环境中显然是不可能的。 第三个 test 稳定输出 1000,方法和我之前用过的 currenthashmap 的用法一样。这里已经去掉了互斥锁。

    那么问题来了:既然互斥锁锁的只是 goroutine,而多个原生线程并发仍然会产生并发错误,那么到底该怎么正确使用互斥锁呢?

    第 1 条附言  ·  99 天前
    把锁换成指针传递成功了。。。。

    看来还是我的理解有问题,互斥锁并不是 goroutine 级别的。。。。
    6 回复  |  直到 2019-07-08 18:06:24 +08:00
        1
    Maboroshii   99 天前
    下面是 go playground 的输出。
    func passes lock by value: sync.Mutex
    这一句, 锁不能用值传递, 改成全局变量或者放在结构体里面再试。


    ./prog.go:38:8: call of func(i int, m sync.Mutex) {
    fmt.Println("Not lock: ", i)
    mutex.Lock()
    fmt.Println("Lock: ", i)
    time.Sleep(time.Second)
    fmt.Println("Unlock: ", i)
    mutex.Unlock()
    defer wait.Done()
    } copies lock value: sync.Mutex
    ./prog.go:30:20: func passes lock by value: sync.Mutex
    ./prog.go:58:8: call of func(c *counter, m sync.Mutex) {
    m.Lock()
    defer m.Unlock()
    c.value++
    wg.Done()
    } copies lock value: sync.Mutex
    ./prog.go:53:25: func passes lock by value: sync.Mutex
    Go vet exited.

    数数:1000

    play.go
        2
    gramyang   99 天前
    @Maboroshii 不行
        3
    gramyang   99 天前
    @Maboroshii 把锁换成指针传递后可以了。。。。。
        4
    Maboroshii   99 天前
    @gramyang #2

    type counter struct {
    sync.Mutex
    value int
    }

    func test2() {
    runtime.GOMAXPROCS(1)
    var wg sync.WaitGroup
    wg.Add(1000)
    c := new(counter)
    c.value=0
    for i := 0; i < 1000; i++ {
    go func(c *counter) {
    c.Lock()
    defer c.Unlock()
    c.value++
    wg.Done()
    }(c)
    }
    wg.Wait()
    fmt.Println("数数:", c.value)
    }

    func main() {
    test2()
    }
        5
    xeaglex   99 天前
    [官方文档]( https://godoc.org/sync) 第一段话说了:

    > Values containing the types defined in this package should not be copied.
        6
    pubby   99 天前
    想起了以前偷懒这样写

    client := &http.Client{}
    t := *( http.DefaultTransport.(*http.Transport))
    t.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
    client.Transport = http.RoundTripper(&t)

    结果高并发时 http 内部锁随机炸
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3641 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 34ms · UTC 05:21 · PVG 13:21 · LAX 22:21 · JFK 01:21
    ♥ Do have faith in what you're doing.