slice/map data safe in multiple goroutines

3,586 views
Skip to first unread message

Color Fuzzy

unread,
Apr 1, 2015, 11:36:51 PM4/1/15
to golan...@googlegroups.com
Map
  1. Multiple append/update/delete to a map will make data not safe, or may crash the program.
  2. ? If only one goroutine change the map, other goroutines just read from the map, will this trigger some problem? Like read a garbage value which is not nil OR just crash the program.
Slice
  1. ? Will multiple goroutine change the same slice cause data problem? Like 1000 append times just add 999 values actually.
  2. ? A goroutine use len(slice) to get length and another goroutine append some data which trigge the underlying array changed, will the len(slice) get the old length OR new length OR just crash because the old array does not exist?

Jesse McNelis

unread,
Apr 1, 2015, 11:52:20 PM4/1/15
to Color Fuzzy, golang-nuts
On Thu, Apr 2, 2015 at 2:36 PM, Color Fuzzy <color...@gmail.com> wrote:
> Map
>
> Multiple append/update/delete to a map will make data not safe, or may crash
> the program.
> ? If only one goroutine change the map, other goroutines just read from the
> map, will this trigger some problem? Like read a garbage value which is not
> nil OR just crash the program.

Yes, concurrent reads and writes to a map is unsafe.

> Slice
>
> ? Will multiple goroutine change the same slice cause data problem? Like
> 1000 append times just add 999 values actually.
> ? A goroutine use len(slice) to get length and another goroutine append some
> data which trigge the underlying array changed, will the len(slice) get the
> old length OR new length OR just crash because the old array does not exist?

The behaviour of data races is undefined. It could crash, it could
silently corrupt other data.

http://golang.org/ref/mem defines what is safe to do.

Color Fuzzy

unread,
Apr 2, 2015, 2:05:13 AM4/2/15
to golan...@googlegroups.com, color...@gmail.com, jes...@jessta.id.au
Thanks for you reply.
That's to say, parallel read/write safety to the same piece of memory should be guaranteed by  programmer, because the thread/process context switch may occur at the middle of read/write(bit struct) operation. 

anl...@gmail.com

unread,
Apr 2, 2015, 12:07:21 PM4/2/15
to golan...@googlegroups.com

Slice
  1. ? Will multiple goroutine change the same slice cause data problem? Like 1000 append times just add 999 values actually.
reading and writing values in paralell (without append, reslice) is OK.

append in paralell to read/write is problem.

  1. ? A goroutine use len(slice) to get length and another goroutine append some data which trigge the underlying array changed, will the len(slice) get the old length OR new length OR just crash because the old array does not exist?

len + append is problem.


Dave Cheney

unread,
Apr 2, 2015, 4:24:06 PM4/2/15
to golan...@googlegroups.com
Append plus Len is not a problem, Len is a property of the slice header which is immutable.

adon...@google.com

unread,
Apr 2, 2015, 5:25:20 PM4/2/15
to golan...@googlegroups.com, anl...@gmail.com
On Thursday, 2 April 2015 12:07:21 UTC-4, anl...@gmail.com wrote:

Slice
  1. ? Will multiple goroutine change the same slice cause data problem? Like 1000 append times just add 999 values actually.
reading and writing values in parallel (without append, reslice) is OK.

 That depends on exactly what you mean.

Every element of an array variable or a slice is a distinct variable.  It's safe for multiple goroutines to access an array concurrently only if no element variable is accessed concurrently by more than one goroutine.

For example, this is safe because each goroutine accesses only one element of the array:

var array [10]int
for i := range array {
    go func(i int) {
        array[i] = i
    }(i)
}

But this is not safe:

var array [10]int
for i := range array {
    go func(i int) {
         array[i] = array[(i+1)%10] + 1 // not safe
    }(i)
}

because each goroutine accesses two variables, each of which is also accessed concurrently by some other goroutine.

Dan Kortschak

unread,
Apr 2, 2015, 5:29:20 PM4/2/15
to Dave Cheney, golan...@googlegroups.com
a = append(a, v) in concurrent with len(a) is a problem

Dave Cheney

unread,
Apr 2, 2015, 5:47:25 PM4/2/15
to Dan Kortschak, golan...@googlegroups.com

Urgh, to the list this time.

I don't believe so, not unless the address of a was passed to another goroutine.

Caleb Spare

unread,
Apr 2, 2015, 5:52:10 PM4/2/15
to Dave Cheney, Dan Kortschak, golan...@googlegroups.com
That's certainly not safe. It's changing a and reading it concurrently.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Dave Cheney

unread,
Apr 2, 2015, 5:55:38 PM4/2/15
to Caleb Spare, Dan Kortschak, golan...@googlegroups.com

It is safe,

go printlength(a)
a = append(a, v)

There is no race here, a is an immutable value

Caleb Spare

unread,
Apr 2, 2015, 5:58:30 PM4/2/15
to Dave Cheney, Dan Kortschak, golan...@googlegroups.com
It's definitely a race.


a is immutable in the same way that an int is immutable; you can still assign on top of it, which is what's happening here, and doing it concurrently with reading is unsafe.

Alan Donovan

unread,
Apr 2, 2015, 6:02:06 PM4/2/15
to Caleb Spare, Dave Cheney, Dan Kortschak, golan...@googlegroups.com
On 2 April 2015 at 17:57, Caleb Spare <ces...@gmail.com> wrote:
It's definitely a race.


a is immutable in the same way that an int is immutable; you can still assign on top of it, which is what's happening here, and doing it concurrently with reading is unsafe.

On Thu, Apr 2, 2015 at 2:55 PM, Dave Cheney <da...@cheney.net> wrote:

It is safe,

go printlength(a)
a = append(a, v)

There is no race here, a is an immutable value


In Dave's example, he's making a copy of the slice, also called a, so there is no race.

In Caleb's example, the two goroutines are referring to the same variable a, so there is a race, but the problem is nothing to do with append or len and entirely to do with assigning to a variable a while another goroutine is loading its value.

Caleb Spare

unread,
Apr 2, 2015, 6:06:55 PM4/2/15
to Dave Cheney, Dan Kortschak, golan...@googlegroups.com
OK I agree that your specific example is okay, because parameters to go functions (println in this case) are evaluated before the goroutine is spawned.

But that's not how I would necessarily interpret Dan's original statement

a = append(a, v) in concurrent with len(a) is a problem

​So if you write

go func() { fmt.Println(len(a)) }()
a
​ = append(a, v)

or

go func() { a = append(a, v) }()
fmt.Println(len(a))

or any of several other interpretations of the statement, those are all racy.

-Caleb​

Dave Cheney

unread,
Apr 2, 2015, 6:10:20 PM4/2/15
to golan...@googlegroups.com
As Alan said, that's got nothing to do with accessing the Len field of the slice header, and everything to do with capturing the address of a via an anon function.

Dave Cheney

unread,
Apr 2, 2015, 6:10:58 PM4/2/15
to golan...@googlegroups.com

Caleb Spare

unread,
Apr 2, 2015, 6:13:28 PM4/2/15
to Dave Cheney, Dan Kortschak, golan...@googlegroups.com
because parameters to go functions (println in this case)

of course that should be printlength, and Alan phrased it better: you're making a copy of the slice by virtue of putting it in a function call.

Dan Kortschak

unread,
Apr 2, 2015, 7:11:43 PM4/2/15
to Dave Cheney, golan...@googlegroups.com
Yes, but the way it was phrased left a lot of possibility for misinterpretation. This is what I was getting at.
Reply all
Reply to author
Forward
0 new messages