关于 golang 互斥锁的一个疑问 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
gramyang

关于 golang 互斥锁的一个疑问

  •  
  •   gramyang Jul 8, 2019 3580 views
    This topic created in 2487 days ago, the information mentioned may be changed or developed.

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

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

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

    Supplement 1    Jul 8, 2019
    把锁换成指针传递成功了。。。。

    看来还是我的理解有问题,互斥锁并不是 goroutine 级别的。。。。
    6 replies    2019-07-08 18:06:24 +08:00
    Maboroshii
        1
    Maboroshii  
       Jul 8, 2019
    下面是 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
    gramyang
        2
    gramyang  
    OP
       Jul 8, 2019
    @Maboroshii 不行
    gramyang
        3
    gramyang  
    OP
       Jul 8, 2019
    @Maboroshii 把锁换成指针传递后可以了。。。。。
    Maboroshii
        4
    Maboroshii  
       Jul 8, 2019
    @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()
    }
    xeaglex
        5
    xeaglex  
       Jul 8, 2019
    [官方文档]( https://godoc.org/sync) 第一段话说了:

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

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

    结果高并发时 http 内部锁随机炸
    About     Help     Advertise     Blog     API     FAQ     Solana     1015 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 22:24 PVG 06:24 LAX 15:24 JFK 18:24
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86