var a string
var done bool
func setup() {
a = "hello, world"
done = true
}
func doprint() {
if !done {
once.Do(setup)
}
print(a)
}
func twoprint() {
go doprint()
go doprint()
}
Code Analysis
Variables:
- a and b are global variables of type int, shared by all goroutines.
Functions:
- f():
- Writes to a and b sequentially (a = 1 and b = 2).
- g():
- Reads and prints b followed by a.
Concurrency in main():
- The function f() is executed as a separate goroutine using go f().
- The function g() is executed directly in the main goroutine.
Potential Issues:
- The goroutine running f() and the main goroutine executing g() run concurrently.
- The writes to a and b in f() may not complete before g() reads and prints the values of a and b.
- This introduces a data race, where concurrent access (writes in f() and reads in g()) occurs on shared memory (a and b) without synchronization.
Possible Outcomes
Due to the lack of synchronization, the program's output is non-deterministic. Here are the possible scenarios:
Case 1: g() executes before f() modifies a and b:
- Initial values of a and b are 0 (default for uninitialized int in Go).
0
0
or
CASE 2: If b = 2 is completed before g() but a = 1 is not, the output could be:
2
0
Key Observations
Data Race: The concurrent access to a and b without synchronization introduces a data race. This makes the program's behavior undefined and unpredictable
Fixing the Code
- Using a
sync.WaitGroup:
Ensure f() completes before g() executes
var a, b int
var wg sync.WaitGroup
func f() {
a = 1
b = 2
wg.Done()
}
func g() {
print(b)
print(a)
}
func main() {
wg.Add(1)
go f()
wg.Wait()
g()
}
- Using Channels: Signal when f() is done:
var a, b int
func f(done chan bool) {
a = 1
b = 2
done <- true
}
func g() {
print(b)
print(a)
}
func main() {
done := make(chan bool)
go f(done)
<-done
g()
}
Here, g() waits until f() sends a signal over the done channel.
Top comments (0)