这个错误折磨了一天。主要是没有真的找到这个错误这句话。一直在找gorequest的错。
goroutine 29737 [runnable]:
internal/poll.runtime_pollWait(0x7f94185392d8, 0x72)
/usr/local/go/src/runtime/netpoll.go:302 +0x89
internal/poll.(*pollDesc).wait(0xc00277ee80?, 0xc0044b2ae1?, 0x0)
/usr/local/go/src/internal/poll/fd_poll_runtime.go:83 +0x32
internal/poll.(*pollDesc).waitRead(...)
/usr/local/go/src/internal/poll/fd_poll_runtime.go:88
internal/poll.(*FD).Read(0xc00277ee80, {0xc0044b2ae1, 0xc5e, 0xc5e})
/usr/local/go/src/internal/poll/fd_unix.go:167 +0x25a
net.(*netFD).Read(0xc00277ee80, {0xc0044b2ae1?, 0xd?, 0xc0027f10e8?})
/usr/local/go/src/net/fd_posix.go:55 +0x29
net.(*conn).Read(0xc001698270, {0xc0044b2ae1?, 0x10?, 0x10?})
/usr/local/go/src/net/net.go:183 +0x45
crypto/tls.(*atLeastReader).Read(0xc003270420, {0xc0044b2ae1?, 0x0?, 0xc0047e6823?})
/usr/local/go/src/crypto/tls/conn.go:785 +0x3d
bytes.(*Buffer).ReadFrom(0xc00339e978, {0x11762e0, 0xc003270420})
/usr/local/go/src/bytes/buffer.go:204 +0x98
crypto/tls.(*Conn).readFromUntil(0xc00339e700, {0x1176ea0?, 0xc001698270}, 0x655499?)
/usr/local/go/src/crypto/tls/conn.go:807 +0xe5
crypto/tls.(*Conn).readRecordOrCCS(0xc00339e700, 0x0)
/usr/local/go/src/crypto/tls/conn.go:659 +0xae5
crypto/tls.(*Conn).readRecord(...)
/usr/local/go/src/crypto/tls/conn.go:582
crypto/tls.(*Conn).readHandshake(0xc00339e700)
/usr/local/go/src/crypto/tls/conn.go:1017 +0x6d
crypto/tls.(*clientHandshakeState).doFullHandshake(0xc0027f1be8)
/usr/local/go/src/crypto/tls/handshake_client.go:471 +0x45
crypto/tls.(*clientHandshakeState).handshake(0xc0027f1be8)
/usr/local/go/src/crypto/tls/handshake_client.go:431 +0x3a5
crypto/tls.(*Conn).clientHandshake(0xc00339e700, {0x117c1d0, 0xc0004cab00})
/usr/local/go/src/crypto/tls/handshake_client.go:230 +0x64a
crypto/tls.(*Conn).handshakeContext(0xc00339e700, {0x117c240, 0xc0053c3020})
/usr/local/go/src/crypto/tls/conn.go:1460 +0x32f
crypto/tls.(*Conn).HandshakeContext(...)
/usr/local/go/src/crypto/tls/conn.go:1403
net/http.(*persistConn).addTLS.func2()
/usr/local/go/src/net/http/transport.go:1537 +0x71
created by net/http.(*persistConn).addTLS
/usr/local/go/src/net/http/transport.go:1533 +0x345
事实上上面的错误是下面这玩意儿引起的。
fatal error: concurrent map writes
fatal error: concurrent map writes
能出现以上情况的示例
var mMap map[int]int
func TestMyMap(t *testing.T) {
mMap = make(map[int]int)
for i := 0; i < 5000; i++ {
go func() {
mMap[i] = i
}()
go readMap(i)
}
}
func readMap(i int) int {
return mMap[i]
}
怎样避免呢?
尽量少定义全局map变量
如果必须定义全局map变量,可以加锁
优化1.可以采用cow策略,read不加锁,每次修改copy修改,再赋值
优化2.可以采用分片锁,减小锁的粒度
优化3.sync.map
以下是读写锁的方式
package main
import (
"sync"
)
func main() {
TestMyMap()
}
type SMap struct {
sync.RWMutex
Map map[int]int
}
func (l *SMap) readMap(key int) (int, bool) {
l.RLock()
value, ok := l.Map[key]
l.RUnlock()
return value, ok
}
func (l *SMap) writeMap(key int, value int) {
l.Lock()
l.Map[key] = value
l.Unlock()
}
var mMap *SMap
func TestMyMap() {
mMap = &SMap{
Map: make(map[int]int),
}
for i := 0; i < 5000; i++ {
go func() {
mMap.writeMap(i, i)
}()
go readMap(i)
}
}
func readMap(i int) (int, bool) {
return mMap.readMap(i)
}
未经允许不得转载:微信 美文-微信文章库-我的知识库 » fatal error: concurrent map writes