每日一個 Golang Packages 06/11 sync

Aliliin發表於2020-06-11

2020/06/11

package main
import (
    "fmt"
    "math/rand" 
    "sync" 
    "time"
)

var ticket int = 10
var mutex sync.Mutex // 建立互斥鎖
var wg sync.WaitGroup // 建立同步等待組
var rwMutex sync.RWMutex // 建立讀寫鎖

func main() {
  wg.Add(7)
  // 臨界資源問題,會出現超賣的現象 (互斥鎖)
  go getRich("脫貧機會1")
  go getRich("脫貧機會2")
  go getRich("脫貧機會3")

  // 讀寫鎖
  go writeData(1)
  go readData(1)
  go writeData(2)
  go readData(2)

  wg.Wait() // main 等待

  fmt.Println("程式結束")
}

func getRich(task string) {
    rand.Seed(time.Now().UnixNano()) // 生成隨機數量
    defer wg.Done()

    for {
        mutex.Lock() // 上鎖之後,只能有一個 goroutine 執行
        if ticket > 0 {
            time.Sleep(time.Duration(rand.Intn(1000)) * time.Microsecond)
            fmt.Println("脫貧人口在減少:", ticket)
            ticket--
        } else {
            mutex.Unlock() // 解鎖
            fmt.Println(task, "用完了,你註定是窮人了!")
            break
        }
        mutex.Unlock() // 使用互斥鎖的時候操作結束之後,一定要解鎖
    }
}

// 可以多個 goroutine 同時讀
func readData(i int) {
    defer wg.Done()

    fmt.Println(i, "read start ...")
    rwMutex.RLock() // 讀操作上鎖
    fmt.Println(i, "reading...")
    time.Sleep(3 * time.Second)
    rwMutex.RUnlock() // 讀操作解鎖
    fmt.Println(i, "read over ...")
}

// 寫的時候加鎖,不能讀也不能寫
func writeData(i int) {
    defer wg.Done()

    fmt.Println(i, "write start ...")
    rwMutex.Lock()
    fmt.Println(i, "writing ...")
    time.Sleep(3 * time.Second)
    rwMutex.Unlock() // 寫操作解鎖
    fmt.Println(i, "write over ...")
}

順便佛系一下用 go 做做 leetcode 的練習題同步到了 GitHub 大家也可以看看。

一步一個腳印,穩紮穩打,重新出發!從基本的 Golang Packages 記憶開始,堅持 ing!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

高永立

相關文章