Do I need to hold a lock of a struct to read the member concurrently?

1,912 views
Skip to first unread message

김용빈

unread,
Jan 10, 2021, 4:30:16 AM1/10/21
to golang-nuts
I have a struct that will be used concurrently.

type A struct {
    sync.Mutex
    id string
    // other members
    ...
}

The other members of A will be concurrently read or written. So I think I have to hold lock of A for those.

But A.id will be written once at creation time of A (when it was not handled concurrently, yet) and will only be read after then.

Should I lock A to read A.id, or is it safe to read concurrently without it?

Thanks in advance.

Axel Wagner

unread,
Jan 10, 2021, 4:53:29 AM1/10/21
to 김용빈, golang-nuts
Short answer: Yes, it's safe.

IMO it's always fun to try and find the answer in the docs though, so long answer:

According to the Go memory model

The Go memory model specifies the conditions under which reads of a variable in one goroutine can be guaranteed to observe values produced by writes to the same variable in a different goroutine.

Now, the only write you do to `A.id` is at creation time, so the question is, is that modification concurrent with other reads or does it "happen before" the reads? The answer is most likely, that it happens before - I assume you initialize the variable and only create goroutines reading it after that, so 1. the write happens-before the go statement, because of the rule "Within a single goroutine, the happens-before order is the order expressed by the program." and 2. that go statement happens-before any reads in that goroutine, because of the rule about goroutine creation. So, because happens-before is transitive, the write happens-before the reads. And because it's the only write, it's safe.

There is a small caveat though: The Memory model speaks about "reads/writes of a variable". Maybe this still isn't safe, because you write to a variable holding an A concurrently (even though you access different fields)? Well, let's see what the spec has to say about variables:

Structured variables of array, slice, and struct types have elements and fields that may be addressed individually. Each such element acts like a variable.

Okay, so every field can be treated as its own variable. Thus, applying the rules of the memory model to individual fields is correct.

--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/1e7df2af-b26e-403f-a8a4-41170b2d2aeen%40googlegroups.com.

김용빈

unread,
Jan 10, 2021, 6:56:40 AM1/10/21
to golang-nuts
Thank you Wagner, as always!

Yes, I asked because it is a field of a struct. With your answer, now I can sure what I wrote is correct or not.

And also thanks for your guide to official documents. I will check them first next time.


2021년 1월 10일 일요일 오후 6시 53분 29초 UTC+9에 axel.wa...@googlemail.com님이 작성:

Axel Wagner

unread,
Jan 10, 2021, 7:36:39 AM1/10/21
to 김용빈, golang-nuts
On Sun, Jan 10, 2021 at 12:57 PM 김용빈 <kyb...@gmail.com> wrote:
Thank you Wagner, as always!

Yes, I asked because it is a field of a struct. With your answer, now I can sure what I wrote is correct or not.

And also thanks for your guide to official documents. I will check them first next time.

No worries, I wasn't trying to call you out or anything, it's a lot of material :) I just genuinely find it fun to do
 

김용빈

unread,
Jan 10, 2021, 7:52:55 AM1/10/21
to golang-nuts
Haha, thanks. I didn't feel get pushed. :)

2021년 1월 10일 일요일 오후 9시 36분 39초 UTC+9에 axel.wa...@googlemail.com님이 작성:
Reply all
Reply to author
Forward
0 new messages