Home > database >  Why Go detects concurrenct read,write problem only on map type?
Why Go detects concurrenct read,write problem only on map type?

Time:10-10

We know that map are unsafe to concurrent read/writes, so are slices. But why Go only detects map ?

Like code below :

package main

import (
    "time"
)

func main() {
    m := map[string]int{"a":1}
    s := []int{1}

    for i := 0; i < 1000; i   {
        go func() {
            m["a"] = i
            s[0] = i
        }()
    }

    time.Sleep(3 * time.Second)
}

Only panics on map:

fatal error: concurrent map writes

goroutine 103 [running]:
...

CodePudding user response:

Firstly, assuming we're talking about modifying the contents of the slice (not the slice definition itself), slices are safe for concurrent read/write so long as you don't concurrently modify the same exact element at the same time. This means that to accurately detect incorrect concurrent access, you would need to track it on a per-element basis. This would be an excessive memory overhead.

Secondly, slices are intended as a thin abstraction over arrays, which themselves are a thin abstraction over direct memory access (within a constrained range). That is to say, the operation is expected to be very fast. Detecting incorrect concurrent access at the language level would be an excessive processing overhead.

In the case of maps, both the memory and processing overhead of using the data structure in the first place is enough to dwarf the cost of running this concurrency check. Therefore, it is seen as a net-positive to have this handy safety feature built in.

You can indeed detect data races on slices using Go's race detector, but as noted by the documentation:

The cost of race detection varies by program, but for a typical program, memory usage may increase by 5-10x and execution time by 2-20x.

CodePudding user response:

The builtin race detector in maps is low-hanging fruit. The feature uses a spare bit in the map header for storage. The feature has a very low CPU cost. Search for hashWriting in runtime/map.go to see the implementation.

A builtin in race detector for slices will incur memory overhead, CPU overhead or both because each slice element is a separate variable in the memory model. There's not a spare bit per slice element to use in a race detector implementation.

Use the Go Race Detector to detect all data races including races on slice elements. The Go Race Detector instruments the code to record and detect how memory is accessed.

  • Related