Race Condition with concurrent Map - what is the problem

I have created a concurrent map in golang guarded by Mutex, but still, when two goroutines modify the map, golang panics with concurrent map access and map writes exception, I don’t know what to do more to stop this race condition from happening.

package main

import (
	"os"
	"fmt"
	"io/ioutil"
	"strings"
	"sync"
)

type concurrentMap struct{
	sync.Mutex
	urls map[string]int
}

func (c *concurrentMap) addToMap(url string) {
	c.Lock()
	if val , ok := c.urls[url];ok{
		c.urls[url] = val + 1
	}else{
		c.urls[url] = 1
	}
	c.Unlock()

}



func NewConcurrentMap() *concurrentMap {
	return &concurrentMap{
		urls:make(map[string]int),
	}
}


func (c *concurrentMap) getUrls() map[string]int {
	return c.urls
}


func main(){
	c := NewConcurrentMap()
	var waitGroup sync.WaitGroup
	file_path := os.Args[1]
	contents , err := ioutil.ReadFile(file_path)
	if err != nil {
		fmt.Println(err)
		return
	}
	fileContents := string(contents)
	lines := strings.Split(fileContents,"\n")
	half := len(lines) / 2

	go func(subset []string){
		waitGroup.Add(1)
		defer waitGroup.Done()
		for _,line := range subset {
			data := strings.Split(line,",")
			if len(data) < 2{
				continue
			}
			url := data[1]
			c.addToMap(url)
		}
	}(lines[0:half])

	go func(subset []string){
		waitGroup.Add(1)
		defer waitGroup.Done()
		for _,line := range subset {
			data := strings.Split(line,",")
			if len(data) < 2{
				continue
			}
			url := data[1]
			c.addToMap(url)
		}
	}(lines[half+1:])
	waitGroup.Wait()

	fmt.Println(c.getUrls())
}

I think the trouble is you are adding the goroutine to Wait group inside the goroutine. Then

waitGroup.Add(1)
go func(subset []string){
defer waitGroup.Done()
for _,line := range subset {
data := strings.Split(line,",")
if len(data) < 2{
continue
}
url := data[1]
c.addToMap(url)
}
}(lines[0:half])

waitGroup.Add(1)
go func(subset []string){
	defer waitGroup.Done()
	for _,line := range subset {
		data := strings.Split(line,",")
		if len(data) < 2{
			continue
		}
		url := data[1]
		c.addToMap(url)
	}
}(lines[half+1:])

waitGroup.Wait()
2 Likes

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