Would you ever have to lock const with a mutex lock? - go

I am programming in go and using mutex lock to lock certain variables so they cannot be overwritten while being read.
This got me thinking. Since you can read a variable multiple times. Is there a scenario where you ever have to lock a constant variable?

The rule is simple: if multiple goroutines access a variable concurrently, and at least one of the accesses is a write, then synchronization is required.
If we talk about constants, then there is no variable, and you cannot take the address of a constant (for details, see Find address of constant in go), so it is not possible to modify constant values.
You do not need any synchronization to access constants from multiple goroutines.

If you talk about constants there is no need to use sync routines to access them (as #icza suggests).
But if you consider const as variable whose value cannot be changed once it has been assigned a value, then you should be careful because of golang memory model and happens before relationship.

Related

Should I use synchronization for visibility of a single pointer?

As per the reference, it says
Otherwise, each read of a single-word-sized or sub-word-sized memory location must observe a value actually written to that location (perhaps by a concurrent executing goroutine) and not yet overwritten.
Since a pointer is word-sized, does that mean synchronization is not necessary for mere purpose of visiblity?
No, visibility means that when one goroutine writes to a variable, other goroutines see the change. So, visibility requires synchronization. Otherwise a reading goroutine will possibly see a stale (not updated) value of the variable.

How can I make every routines a global variable for each routine? [duplicate]

This question already has an answer here:
How to make a variable thread-safe
(1 answer)
Closed 8 months ago.
I have a lot of functions in every routines I'm planning to run, but before I reconstruct it to multiple threads, it uses a global variable to send message back.
And after I reconstruct it, the routines write the same variable which causes panic.
So, how could I solve this problem? Is there a way to make a unique global variable for every routine?
Don't use global (package level) variables. If you must, use proper synchronization.
But instead as Go's proverb goes:
Do not communicate by sharing memory; instead, share memory by communicating.
Use channels instead to communicate results which is safe for concurrent use by design.
If there is state all goroutines should have, group the variables describing the state into a struct, and pass a value of that struct to each goroutine, or have them create their own.
See related: How to make a variable thread-safe

Why does Go uses channels to send and receive data between goroutines instead of using normal variables?

I could not find anything about this question except this explanation by Wikipedia https://en.wikipedia.org/wiki/Channel_(programming). But I'm not satisfied with the explanation.
What problem do channels solve?
Why don't we just use normal variables to send and receive data instead?
If by "normal variables" you mean, for example, a slice that multiple goroutines write to and read from, then this is a guaranteed way to get data races (you don't want to get data races). You can avoid concurrent access by using some kind of synchronization (such as Mutex or RWLock).
At this point, you
reinvented channels (which are basically that, a slice under a mutex)
spent more time than you needed to and still your solution is inferior (there's no syntax support, you can't use your slices in select, etc.)
Channels solve the problem of concurrent read and write. Basically, prevent the situation when one goroutine reads a variable and another one writes the same variable.
Also channels may have buffer, so you can write several values before locking.
Of course, you don't have to use channels. There are other ways to send data between goroutines. For example, you can use atomic operations when assigning or reading a value from a shared variable, or use mutex whenever you access it.

A difference between Seed and Rand.Seed

The golang docs says that
Seed, unlike the Rand.Seed method, is safe for concurrent use.
The rand.Seed is actually from math/rand package, but what is Seed? If Seed is another function then it's not present in math/rand so it's unclear from where that function comes from?
update:
I'm exploring the demo program where in main we execute
rand.Seed(time.Now().UnixNano())
go process(...)
go process(...)
where the process is determined like
func process(...) {
time.Sleep(time.Duration(rand.Intn(30)) * time.Second)
...
}
We are using the same seed in two different threads, so is such using of rand.Seed considered to be a thread non-safe?
There is a rand.Seed() function, and there is a Rand.Seed() method. Your quote originates from the documentation of the Rand.Seed() method.
Global functions of the math/rand package operate on a global rand.Rand instance. If you check the source code of rand.Seed():
func Seed(seed int64) { globalRand.Seed(seed) }
The global functions are safe for concurrent use, so all other packages can use it (in a shared manner). The global rand.Rand instance is provided for convenience, you can use it "out-of-the box" without any preparation (except the need to properly seed it) and without any synchronization.
Instances of rand.Rand are not safe for concurrent use, each goroutine that needs a rand.Rand for deterministic random sequences should create one, and seed it appropriately. Or if a rand.Rand is to be shared between multiple goroutines, explicit synchronization is required.
Pros of using the global rand.Rand (via the global functions) are: (1) ease of use (it's implicitly shared with everyone) and (2) no synchronization is needed.
Pros of creating and using a custom rand.Rand instance: (1) it's faster (it's not synchronized implicitly) and (2) you are in control of who has access to it, so you can use it to repeat pseudo-random sequences (you can't do that with the global instance as "anyone" may use it concurrently with you).
Edit:
We are using the same seed in two different threads, so is such using of rand.Seed considered to be a thread non-safe?
You only call rand.Seed once, so actually it doesn't even matter if it's thread safe or not, it is not called concurrently. If rand.Seed() would be called from multiple goroutines concurrently, only then would it matter whether it's safe for concurrent use. And as stated earlier in my answer: "The global functions are safe for concurrent use..."
What you do call from multiple goroutines concurrently is rand.Intn(), but again, it's safe to do that.

Go lang global variables without goroutines overwriting

I'm writing a CMS in Go and have a session type (user id, page contents to render, etc). Ideally I'd like that type to be a global variable so I'm not having to propagate it through all the nested functions, however having a global variable like that would obviously mean that each new session would overwrite it's predecessor, which, needlessly to say, would be an epic fail.
Some languages to offer a way of having globals within threads that are preserved within that thread (ie the value of that global is sandboxed within that thread). While I'm aware that Goroutines are not threading, I just wondered if there was a similar method at my disposal or if I'd have to pass a local pointer of my session type down through the varies nested routines.
I'm guessing channels wouldn't do this? From what I can gather (and please correct me if I'm wrong here), but they're basically just a safe way of sharing global variables?
edit: I'd forgotten about this question! Anyhow, an update for anyone who is curious. This question was written back when I was new to Go and the CMS was basically my first project. I was coming from a C background with familiarity with POSIX thread but I quickly realised a better approach was to write the code in a mode functional design with session objects passed down as pointers in function parameters. This gave me both the context-sensitive local scope I was after while also minimizing the amount to data I was copying about. However being a 7 year old project and one that was at the start of my transition to Go, it's fair to say the project could do with a major rewrite anyway as there are a lot of mistakes made. That's a concern for another day though - currently it works and I have enough other projects on the go at.
You'll want to use something like a Context:
http://blog.golang.org/context
Basically, the pattern is to create a Context for each unique thing you want to do. (A web request in your case.) Use context.WithValue to embed multiple variables in the context. Then always pass it as the first parameter to other methods that are doing further work in other goroutines.
Getting the variable you need out of the context is a matter of calling context.Value from within any goroutine. From the above link:
A Context is safe for simultaneous use by multiple goroutines. Code can pass a single Context to any number of goroutines and cancel that Context to signal all of them.
I had an implementation where I was explicitly sending variables as method parameters, and I discovered that embedding these variables using contexts significantly cleaned up my code.
Using a Context also helps because it provides ways to end long-running tasks by using channels, select, and a concept called a "done channel." See this article for a great basic review and implementation:
http://blog.golang.org/pipelines
I'd recommend reading the pipelines article first for a good flavor of how to manage communication among goroutines, then the context article for a better idea of how to level-up and start embedding variables to pass around.
Good luck!
Don't use global variables. Use Go goroutine-local variables.
go-routine Id..
There are already goroutine-local variables: they are called function
arguments, function return values, and local variables.
Russ
If you have more than one user, then wouldn't you need that info for each connection? So I would think that you'd have a struct per connected user. It would be idiomatic Go to pass a pointer to that struct when setting up the worker goroutine, or passing the pointer over a channel.

Resources