3

I know that golang's bytes.Buffer is not thread-safe but if I have one writer (in a goroutine) and one reader (in another goroutine). Is it safe?

If not, then why is it not? Write appends to the buffer while reads read from the start so I don't see a scenario where they will be accessing the same memory location.

icza
  • 389,944
  • 63
  • 907
  • 827
Keeto
  • 4,074
  • 9
  • 35
  • 58

1 Answers1

9

No, it's not safe.

bytes.Buffer is a struct, and both the Buffer.Read() and Buffer.Write() methods read / modify the same fields of the same struct value (they have pointer receivers). This alone is enough to be unsafe for concurrent use. For more details, see Is it safe to read a function pointer concurrently without a lock?

Also think about that a bytes.Buffer stores bytes in a byte slice, which is a field of the struct. When writing, it might be necessary to sometimes allocate a bigger buffer (if slice capacity is not enough), and so the slice header (the slice struct field) must be changed (in Write()). Without synchronization there's no guarantee that a concurrent Read() will see this.

And... even if no reallocation is needed (because the underlying byte slice has enough capacity to accommodate the data passed to Write()), storing the data in the byte slice requires to reslice it, so the slice header changes even if no reallocation is needed (the length of the slice is also part of the slice header). To see what's in the slice header, check out the reflect.SliceHeader type.

Community
  • 1
  • 1
icza
  • 389,944
  • 63
  • 907
  • 827