Simultaneous writing and reading from the card causes a potential race condition

I have a very basic Golang application that builds and starts an HTTP server. The server has 2 endpoints, one for sending data and one for receiving.

After every POST request to the server, parse the incoming data from the body and push it to the channel. Then I have a function that reads from a pipe and saves the data to the card.

After every GET request to the JSON server, it marshals the map and sends it to the client.

Each HTTP server request is executed asynchronously and the worker function is written to the map synchronously in its own goroutine.

The main pseudo code looks like this:

package main

import (
    "net/http"
)

type dataStore map[string]string

func listenHandler(stream chan string) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // JSON unmarshal request body

        // push data onto stream
        stream <- data
    }
}

func serveHandler(store *dataStore) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // JSON marshal data store
        // serve to client
    }
}

func worker(stream <-chan string) *dataStore {
    store := make(dataStore)
    go func() {
        for data := range stream {
            // process and write data to map
        }
    }()
    return &store
}

func main() {
    stream := make(chan string)
    store := worker(stream)

    http.HandleFunc("/listen", listenHandler(stream))
    http.HandleFunc("/serve", serveHandler(store))

    http.ListenAndServe(":8080", nil)
}

      

I tested and ran the app without issue, however I was told that it has a potential race condition and I'm not sure why. It's true?

+3


source to share


1 answer


In the code above, you are only syncing your entries, not reading; this means you can still read from the map while you write on it, which would be a race condition.



To make it thread safe, you need to wrap both reads and writes in a concurrency structure - either using pipes or a mutex - to ensure that only one thread is accessing it at any given time, if it's writing operations. Multiple threads can safely read concurrently while the thread is not writing. RWMutex

provides this function explicitly.

+2


source







All Articles