About the memo in gopl chapter 9

original code:

Hello, I think it will be faster if I change the Get method to:

func (memo *Memo) Get(key string) (interface{}, error) {
	e := memo.cache[key]
	if e != nil {
		<-e.ready
		return e.res.value, e.res.err
	}

	memo.mu.Lock()
	e = memo.cache[key]
	if e == nil {
		e = &entry{ready: make(chan struct{})}
		memo.cache[key] = e
		memo.mu.Unlock()
		e.res.value, e.res.err = memo.f(key)
		close(e.ready)
	} else {
		memo.mu.Unlock()
		<-e.ready
	}
	return e.res.value, e.res.err
}

Because there will be less locks from memo.mu.Lock().

What do you think? Dose my change has effect?

Thanks.

m := New(httpGetBody)
	var n sync.WaitGroup
	for i := 0; i < 50000; i++ {
		n.Add(1)
		go func() {
			defer n.Done()
			i := i
			key := strconv.Itoa(i % 1000)
			 _, err := m.Get(key)
			if err != nil {
				log.Println(err)
			}
		}()
	}
	n.Wait()

I got this error:
fatal error: concurrent map read and map write

It seems that:

for map[string]*entry, concurrent read + write is not allowed

Correct. You could try a sync.Map. The documentation says it’s “specialized” so it might end up making it worse, so, as always, benchmark it to see if it works better for you.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.