iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
Cloud Native

【하나, 둘, ready, get set, go】系列 第 18

【하나, 둘, ready, get set, go】Day 18 - sync (下)

  • 分享至 

  • xImage
  •  

前情提要

我們在昨天介紹了如何使用 sync.WaitGroup 來進行 Goroutines

今天要來介紹 sync 的另外一個,叫做 sync.Mutex,中文叫做互斥鎖

當同時有很多個 Goroutines 要對一個變數進行修改時,透過使用 Lock()Unlock() 這兩個 method,就可以有效的避免掉資源競爭的問題

下面我們就來玩看看吧~

實際操作

語法

// 宣告一個 Mutex 互斥鎖
var mu sync.Mutex

/*
Lock() 與 Unlock() 是成雙成對的
有 Lock() 就一定要進行 Unlock()
不然的話,會造成 Deadlock,因為阻塞了
*/

// 告訴系統說,對當前的 Goroutines 進行上鎖
// 確保只有當前的 Goroutines 可以對該資源進行存取
mu.Lock()

// 告訴系統說,對當前的 Goroutines 進行解鎖
// 開放其他的 Goroutines 可以對該資源進行存取
mu.Unlock()

下面就用 A Tour of Go 上的官方範例來進行講解

package main

import (
    "fmt"
    "sync"
    "time"
)

// SafeCounter is safe to use concurrently.
type SafeCounter struct {
    mu sync.Mutex
    v  map[string]int
}

// Inc increments the counter for the given key.
func (c *SafeCounter) Inc(key string) {
    c.mu.Lock()
    // Lock so only one goroutine at a time can access the map c.v.
    c.v[key]++
    c.mu.Unlock()
}

// Value returns the current value of the counter for the given key.
func (c *SafeCounter) Value(key string) int {
    c.mu.Lock()
    // Lock so only one goroutine at a time can access the map c.v.
    defer c.mu.Unlock()
    return c.v[key]
}

func main() {
    c := SafeCounter{v: make(map[string]int)}
    for i := 0; i < 1000; i++ {
        go c.Inc("somekey")
    }    
    
    time.Sleep(time.Second)
    fmt.Println(c.Value("somekey"))
}

type SafeCounter struct

  1. 宣告一個 SafeCounter struct,結構內包含 Mutex 與 map 變數 v -> Line 10~13
  2. 撰寫基於 SafeCounter struct 的 method Inc(key string) -> Line 16~21
  3. 撰寫基於 SafeCounter struct 的 method Value(key string) -> Line 24~29

func (c *SafeCounter) Inc(key string)

  1. 使用 *SafeCounter receiver c 的 Mutex mu 將當前的 Goroutines 上鎖 Lock() -> Line 17
  2. *SafeCounter receiver c 的 map v 對應 key 的 value 進行修改 -> Line 19
  3. 使用 *SafeCounter receiver c 的 Mutex mu 將當前的 Goroutines 解鎖 Unlock() -> Line 20

func (c *SafeCounter) Value(key string)

  1. 使用 *SafeCounter receiver c 的 Mutex mu 將當前的 Goroutines 上鎖 Lock() -> Line 25
  2. 回傳 *SafeCounter receiver c 的 map v 對應 key 的 value -> Line 28
  3. 當 function 執行完畢後 defer,使用 *SafeCounter receiver c 的 Mutex mu 將當前的 Goroutines 解鎖 Unlock() -> Line 27

func main()

  1. 宣告一個型別為 SafeCounter 的變數 c -> Line 32
  2. 使用 for 迴圈執行 1000 次 Goroutines function c.Inc("somekey") -> Line 33~35
  3. 休息/等待一秒 -> Line 37
  4. 取得變數 c 裡 map["somekey"] 的對應值,並輸出 -> Line 38

思考一下

如果將 func (c *SafeCounter) Inc(key string) 裡面的 c.mu.Lock()c.mu.Unlock() 註解掉,會發生什麼事呢?

總結

今天簡單介紹了 Goroutines 中 sync.Mutex 的用法

Go 基礎就到這邊先告一段落了,接下來要來開始介紹如何使用 Go 架設後端服務,以及...

明天開始要來介紹,Go 要如何連接 SQL 資料庫~

明天見~


上一篇
【하나, 둘, ready, get set, go】Day 17 - sync (上)
下一篇
【하나, 둘, ready, get set, go】Day 19 - 使用 GORM 連接 SQL 資料庫
系列文
【하나, 둘, ready, get set, go】30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言