代码见 https://github.com/GramYang/GoTest/blob/master/sync/mutex1.go
第一个 test 输出的是小于 1000 的随机值。 第二个 test 稳定输出 1000,但是限制了原生线程的数量,这在工作环境中显然是不可能的。 第三个 test 稳定输出 1000,方法和我之前用过的 currenthashmap 的用法一样。这里已经去掉了互斥锁。
那么问题来了:既然互斥锁锁的只是 goroutine,而多个原生线程并发仍然会产生并发错误,那么到底该怎么正确使用互斥锁呢?
1
Maboroshii 2019-07-08 13:47:54 +08:00
下面是 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 OP @Maboroshii 不行
|
3
gramyang OP @Maboroshii 把锁换成指针传递后可以了。。。。。
|
4
Maboroshii 2019-07-08 14:01:23 +08:00
@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 2019-07-08 17:18:14 +08:00
[官方文档]( https://godoc.org/sync) 第一段话说了:
> Values containing the types defined in this package should not be copied. |
6
pubby 2019-07-08 18:06:24 +08:00
想起了以前偷懒这样写
client := &http.Client{} t := *( http.DefaultTransport.(*http.Transport)) t.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} client.Transport = http.RoundTripper(&t) 结果高并发时 http 内部锁随机炸 |