【go】golang中鎖的用法-互斥鎖

alisleepy發表於2024-04-10

互斥鎖

  1. 解釋:互斥鎖,保證同一時刻只有 1 個 goroutine 訪問共享資源,比如多個協程同時修改同一個檔案,同一時刻只能同一個協程進行修改
  2. 使用方法
// 定義一個互斥鎖
// var 變數名 互斥鎖型別
var guardMutex sync.Mutex

//上鎖
guardMutex.Lock()

// 釋放鎖
guardMutex.Unlock()
  1. 實際demo
package main

import (
	"fmt"
	"sync"
)

// 不帶互斥鎖
type SumStruct struct {
	value int
	wg    sync.WaitGroup
}

// 帶互斥鎖的
type CountStruct struct {
	value int
	wg    sync.WaitGroup // 等待組
	mu    sync.Mutex     // 互斥鎖
}

func main() {
	var sum int
	// 沒有互斥鎖的
	// sum = sumNoMutex()

	// 使用互斥鎖的
	sum = sumUseMutex()
	fmt.Printf("最終sum的值 = %d\n", sum)
}

// 示例1:沒有互斥鎖,多個協程對同一個值進行++,計算最後的結果,最終可能不是500
func sumNoMutex() int {
	sumStruct := SumStruct{}

	// 啟動5個協程
	sumStruct.wg.Add(5)
	for i := 1; i <= 5; i++ {
		go func(w *sync.WaitGroup) {
			defer w.Done()
			for j := 0; j < 100; j++ {
				sumStruct.value = sumStruct.value + 1
			}
		}(&sumStruct.wg)
	}

	// 等待5個協程全部執行完成
	sumStruct.wg.Wait()

	return sumStruct.value
}

// 示例1:互斥鎖 sync.Mutex
func sumUseMutex() int {
	countStruct := CountStruct{}
	countStruct.wg.Add(5)

	// 啟動5個協程,每個協程裡邊進行+1操作
	for i := 0; i < 5; i++ {
		go func(cs *CountStruct) {
			defer cs.wg.Done()
			for j := 0; j < 1000; j++ {
				cs.add()
			}
		}(&countStruct)
	}

	// 等待協程全部執行完成
	countStruct.wg.Wait()
	sum := countStruct.getValue()
	return sum
}

// +1 計算
func (c *CountStruct) add() {
	// 使用互斥鎖,保證同一時刻只有1個協程可修改這個變數
	c.mu.Lock()
	defer c.mu.Unlock()
	c.value++
}

// 獲取最後的值
func (c *CountStruct) getValue() int {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.value
}

相關文章