fatal error: concurrent map writes

fatal error: concurrent map writes

这个错误折磨了一天。主要是没有真的找到这个错误这句话。一直在找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

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

我的知识库