Challenge your understanding of Go's concurrency mechanisms including select statements, mutex locks, and wait groups. This quiz covers key concepts, common pitfalls, and practical usage for efficient parallel programming in Go routines.
Which statement best describes what happens if multiple cases in a Go select statement are ready at the same time?
Explanation: When multiple cases in a Go select statement are ready, one of the ready cases is chosen randomly for execution. Contrary to what some assume, Go does not execute all cases or panic in this situation. The statement also does not block if multiple options are ready; it only blocks if none are ready. Choosing one case at random helps prevent starvation.
What is the main reason for using a Mutex in concurrent Go programs?
Explanation: A Mutex is used in Go to guarantee mutually exclusive access to shared data, preventing race conditions from concurrent writes. While mutexes help avoid data corruption, they do not inherently increase program speed; in fact, improper use can slow a program. Mutexes are unrelated to launching goroutines or preventing their termination; those actions are controlled differently.
Why are WaitGroups commonly used when working with goroutines in Go?
Explanation: WaitGroups provide a way to wait until a collection of goroutines finishes, allowing the main program to proceed only after all tasks are done. They do not schedule goroutines nor are they a tool for race detection. Limiting the number of running goroutines is better handled by semaphores or buffered channels, not WaitGroups.
In which scenario could a Mutex in Go lead to a deadlock?
Explanation: Attempting to lock a Mutex a second time from the same goroutine without unlocking causes a deadlock because the Mutex will never be released. This is a common pitfall when using mutexes. Using WaitGroups or select statements, or properly closing channels, do not inherently cause deadlocks unless misused in combination with other synchronization primitives.
What is the purpose of a default case in a Go select statement?
Explanation: A default case in a select statement allows the function to avoid blocking if none of the channels are ready for communication. It does not set channel priorities or close channels, nor does it mean the code waits for all cases to become ready. Therefore, only the first option is correct here.
What issue may arise if WaitGroup.Done is called more times than WaitGroup.Add in a Go program?
Explanation: Calling Done more times than Add results in a negative counter, which causes the WaitGroup to panic at runtime. This is a critical error in goroutine synchronization. The speed of goroutines or use of channels is unaffected, and mutexes are unrelated to this behavior.
After acquiring a Mutex lock in Go, where is the recommended location to place the Unlock call?
Explanation: The best practice is to place Unlock in a defer statement immediately after acquiring the lock. This ensures that the mutex is always released, even if errors or returns occur. Unlocking randomly, after each assignment, or outside the function is incorrect and may lead to further mistakes or deadlocks.
What happens when a Go select statement includes a receive operation on a closed channel?
Explanation: Receiving from a closed channel returns the zero value for the data type and does not result in blocking. It does not cause a panic when reading, and the case is not skipped if it is ready. Blocking forever only occurs when all channels are open and none are ready, which is not the case with a closed channel.
Which method is used to increase the counter of a WaitGroup in Go when adding more goroutines to wait for?
Explanation: The Add method increases the internal counter of a WaitGroup to register additional goroutines to wait for. There are no Increment, Next, or Up methods available for WaitGroup in Go, so those are incorrect options.
What is the effect of a select statement in Go with no cases inside it?
Explanation: A select with no cases will block forever, effectively creating a deadlock and halting any further execution in that goroutine. It does not log a warning, execute instantly, or launch new goroutines automatically. This pattern is sometimes used deliberately to block but can also be an error.