CodeBlanks Logo Icon CodeBlanks

sync.Mutex

Learn to synchronize access to shared data with a Mutex.

sync.Mutex

If several goroutines write the same variable at once, a data race happens and the result is unpredictable. sync.Mutex lets only one goroutine run a piece of code at a time:

var mu sync.Mutex
sayac := 0

mu.Lock()
sayac++
mu.Unlock()

The region between Lock and Unlock is called the critical section.

defer Unlock and the race detector

Forgetting to unlock freezes the program (deadlock). The safest pattern is to write defer right after locking:

func (s *Sayac) Artir() {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.n++
}

To find races use go test -race or go run -race. A struct containing a mutex must not be copied, which is why its methods use pointer receivers.

Practice Safe counter

Write type Sayac struct { mu sync.Mutex; n int } and a locked Artir() method. Each of 100 goroutines calls Artir once; wait with a sync.WaitGroup and print n.

Starter code

main.go
package main

import (
    "fmt"
    "sync"
)

func main() {
    // buraya yaz
}

Sample solution

main.go
package main

import (
    "fmt"
    "sync"
)

type Sayac struct {
    mu sync.Mutex
    n  int
}

func (s *Sayac) Artir() {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.n++
}

func main() {
    var s Sayac
    var wg sync.WaitGroup
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            s.Artir()
        }()
    }
    wg.Wait()
    fmt.Println(s.n)
}

Expected output

100

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Why isn't <code>sayac++</code> safe without a lock?

  • An int can't be shared
  • The compiler doesn't allow it
  • Read-increment-write is three steps; another goroutine can interleave Correct answer
  • The ++ operator is slow

Explanation: If two goroutines read the same old value and each add one, an increment is lost. go run -race catches this race.

2 Unlock

Question
s.mu.Lock()
____ s.mu.Unlock()
s.n++
Answer
s.mu.Lock()
defer s.mu.Unlock()
s.n++

Explanation: defer Unlock guarantees the lock is released however the function ends.

3 Concept

Term Meaning
Data race Unprotected concurrent access
Critical section Between Lock and Unlock
Deadlock A lock never released
-race Race detector

All lessons in Intermediate