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
cmd/compile: racy writes to global var not observed #59088
Comments
I don't think this is a bug. There is no synchronization in your code. A program with a data race in it is not a valid Go program and it could do anything. |
@wdvxdr1123 It is not allowed to do "anything", it still must adhere to the Go memory model. But in this case, it is allowed to not observe the racy write to |
I believe this is valid behavior according to the memory model |
@seankhliao Please remind me how does the memory model make the output results different, between |
@seankhliao run the above code with |
In the presence of data races:
In both instances, the program observes some valid value (initial write, write by other goroutine). |
@seankhliao I am afraid we are talking about different things.
|
Let me clear up some things: 1, The memory model specifies a set of allowed behaviours, and a compiled program is deemed valid if its behaviour aligns with one of the allowed ones. As a result, 2 programs can express different behaviours and be both valid. In this case, the Go memory model says that the result of a racy load from a larger-than-word variable 2, The memory model does not have a notion of wall clock, or real time, in the memory model, 1 action either happens before, at the same time or after another action. This happen-before relationship is a mathematical relationship defined and described in the memory model and has nothing to do with actual before-ness in terms of real time. In this program, the load 3, Raciness, defined by the Go memory model is a property of a Go program, not the property of the compiled code. The raciness of which is defined by the memory model of the hardware architecture. As a result, multithreading reasoning must be performed on the Go source code, and in this case, analysis shows raciness in the |
@merykitty Am I right to restate your explanation as follows: (1) When the number of instructions near In my opinion, the default compiler should be designed to translate the code and make it run as it looks like. Not in the other way around: the relation of |
@huzhiwen93 It seems to me that you are not used to working with concurrency at this low level, so I think that my attempt to explain the rationales behind the memory model would be futile. As a result, I will kindly refer to you the excellent blogs from Russ about this subject, which may clear up much of your confusion. |
History shows that that this really really hard to define. Different people have completely different intuitions about what it means to "run as it looks like." That said, I am surprised that in this case the |
The memory state of that loop is never used. No |
Thanks. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?darwin, centos
go env
OutputWhat did you do?
Directly run the following code, you will see that the program keeps printing 0, which is not expected.
But if we uncomment the line with [tag A], or uncomment the line with [tag B], or run the program with
gcflag='-N -l'
, then the program can print results greater than 0, which is as expected.Another experiment: If we change the line with [tag 1] as
newX := X{X0:1}
, then we have to further comment the line with [tag 2] to reproduce the 'all zero output' result. It seems to be related with the amount of instructions nearby.By comparing the assembly codes generated by
go tool compile
(shown in the figure below), we find that the entirefor
loop in functionchange()
is wiped out, probably because the optimizer infers that those lines of code do not make any influences.The above test code was originally written to test the consistency during
struct
copy. And a real-world project might not be easy to trigger this bug. But it indeed reveals a defect in go compiler, which needs to be reviewed.This issue has been testified by my colleagues.
The text was updated successfully, but these errors were encountered: