GO:lack of synchronization

mridul037

mridul037

Posted on November 27, 2024

GO:lack of synchronization
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()
}
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

or

CASE 2: If b = 2 is completed before g() but a = 1 is not, the output could be:

2
0
Enter fullscreen mode Exit fullscreen mode

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

  1. 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()
}

Enter fullscreen mode Exit fullscreen mode
  1. 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()
}

Enter fullscreen mode Exit fullscreen mode

Here, g() waits until f() sends a signal over the done channel.

💖 💪 🙅 🚩
mridul037
mridul037

Posted on November 27, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related