1

Data Races di Golang: Fixing with Mutex

 2 years ago
source link: https://dev.to/ynwd/data-races-di-golang-fixing-with-mutex-4d80
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
ynwd

Posted on Nov 13

Data Races di Golang: Fixing with Mutex

Sebelumnya, kita telah membahas data race di golang dan channel. Sekarang kita akan mencoba memperbaiki data races dengan mutex.

Tapi sebelumnya, kita akan menambahkan sebuah struct text serta getter-setter-nya dan mengubah fungsi getText(), menjadi seperti ini:

package main

import (
    "fmt"
)

func getText() string {
    i := text{txt: "hi"}
    go func() {
        i.Set("hello")
    }()
    return i.Get()
}

type text struct {
    txt string
}

func (t *text) Set(txt string) {
    t.txt = txt
}

func (t *text) Get() string {
    return t.txt
}

func main() {
    fmt.Println(getText())
}

Enter fullscreen modeExit fullscreen mode

Kalau dilihat secara sequence diagram, ia mirip dengan kode sebelumnya.

  • Go routine #1 : main()
  • Go routine #2 : fungsi di mana i.Set() dipanggil.

Dan jika kita jalankan dengan -race:

go run -race main.go  
Enter fullscreen modeExit fullscreen mode

Maka ia juga akan menghasilkan warning:

hi
==================
WARNING: DATA RACE
Write at 0x00c000012230 by goroutine 7:
  main.(*text).Set()
      /Users/pro/Documents/apps/cms/cmd/main.go:20 +0x33
  main.getText.func1()
      /Users/pro/Documents/apps/cms/cmd/main.go:10 +0x2e

Previous read at 0x00c000012230 by main goroutine:
  main.(*text).Get()
      /Users/pro/Documents/apps/cms/cmd/main.go:24 +0xda
  main.getText()
      /Users/pro/Documents/apps/cms/cmd/main.go:12 +0xf1
  main.main()
      /Users/pro/Documents/apps/cms/cmd/main.go:28 +0x24

Goroutine 7 (running) created at:
  main.getText()
      /Users/pro/Documents/apps/cms/cmd/main.go:9 +0xd0
  main.main()
      /Users/pro/Documents/apps/cms/cmd/main.go:28 +0x24
==================
Found 1 data race(s)
exit status 66
Enter fullscreen modeExit fullscreen mode

Solusi dengan mutex

Mutex gunanya untuk mencegah agar sebuah variabel tidak diakses secara bersamaan.

Implementasinya sangat mudah. Kita tinggal menempatkan saja method Lock dan Unlock di variabel yang terkena data races.

package main

import (
    "fmt"
    "sync"
)

func getText() string {
    i := text{txt: "hi"}
    go func() {
        i.Set("hello")
    }()
    return i.Get()
}

type text struct {
    txt   string
    mutex sync.Mutex
}

func (t *text) Set(txt string) {
    t.mutex.Lock()
    defer t.mutex.Unlock()
    t.txt = txt
}

func (t *text) Get() string {
    t.mutex.Lock()
    defer t.mutex.Unlock()
    return t.txt
}

func main() {
    fmt.Println(getText())
}

Enter fullscreen modeExit fullscreen mode

Jika kita jalankan dengan -race, hasilnya:

$ go run -race main.go                                                     main*
hi
Enter fullscreen modeExit fullscreen mode

Yang menjadi pertanyaan: mengapa hasilnya tetap hi?

Jawabannya adalah: karena go routine #1 (main), selesainya lebih dulu dan langsung exit.

Walaupun go routine ke-2 sedang berjalan, karena go routine #1 sudah exit duluan, ya sudah, program selesai.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK