New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sync: Once uses, but doesn't need atomic operations #22104
Comments
Please review this change which added the fast path atomic operation
93dde6b
…On Mon, Oct 2, 2017 at 11:02 PM, Jelte Fennema ***@***.***> wrote:
What version of Go are you using (go version)?
1.9
Does this issue reproduce with the latest release?
Yes, code is here: https://github.com/golang/go/
blob/master/src/sync/once.go#L35-L46
What did you expect to see?
To see synchronised access to o.done, but not excessively synchronising.
What did you see instead?
It's synchronised using atomic load and store and using a mutex.
Proposed fix
As far as I can tell there is no reason why load and store to o.done have
to be atomic. The write is already synchronised using the mutex and before
running f a second time the value of o.done is checked inside the mutex.
So my fix would simply be to use non atomic operations on o.done.
I don't mind creating a PR myself, but would like to be sure that I'm not
overlooking something before doing so.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#22104>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAAcAyEIRWO8v3XTjvNrtQbZnHNZgq7eks5soNDegaJpZM4Pqitb>
.
|
I was super confused at first that the exact oposite change would have an advantage. But after looking more closely it adds both the fast path and the atomic operation in the same PR. What I'm suggesting is doing the fast path change without the atomic operation, just do it non atomic (maybe with a boolean like it was before). |
Related question, are there docs somewhere on how to run these benchmarks myself? |
that would potentially introduce a data race
These are standard Go testing benchmarks. |
The atomic load is required. Without it, the second caller of |
@randall77 I believe in this case stale reads are OK since the slow path actually has to relock and recheck anyway. This is not to say that there isn't a race there, but I believe on modern platforms with support for hardware atomic read / write with 32bit memory this would be impossible. @JelteF I think you'd need some sort of |
Oh wow, and also need to have correct alignment for atomic operations. I think the added complexity isn't worth it, it isn't the go way. |
@skabbes: You're right that the atomic load is not required for the slow path. But the atomic load is required for the fast path, when it reads a 1 and immediately returns. There needs to be some synchronization so that the second+ callers of |
Completely didn't think about that as an API guarantee, but it definitely is. Kudos. |
Thank you for the discussion. I’m going to close this as there is no obvious change required. If you wish to continue to discuss this, please see https://golang.org/wiki/Questions for good places to ask. Thanks. |
Thanks for the feedback everyone. I learnt something new about dataraces, namely that they are possible even when the read and assignment is guarded by a mutex. I checked out moving the atomic load to the slow instead of the fast path and the race detector was still complaining. Even with your comments it's still not clear to me why that would not be a valid solution. |
@JelteF let's take this off the issue tracker, please see https://golang.org/wiki/Questions for good places to ask. Thanks. |
What version of Go are you using (
go version
)?1.9
Does this issue reproduce with the latest release?
Yes, code is here: https://github.com/golang/go/blob/master/src/sync/once.go#L35-L46
What did you expect to see?
To see synchronised access to
o.done
, but not excessively synchronising.What did you see instead?
It's synchronised using atomic load and store and using a mutex.
Proposed fix
As far as I can tell there is no reason why load and store to
o.done
have to be atomic. The write is already synchronised using the mutex and before runningf
a second time the value ofo.done
is checked inside the mutex. So my fix would simply be to use non atomic operations ono.done
.I don't mind creating a PR myself, but would like to be sure that I'm not overlooking something before doing so.
The text was updated successfully, but these errors were encountered: