1. 程式人生 > 其它 >Golang sync.Mutex包——互斥鎖

Golang sync.Mutex包——互斥鎖

1、概述

Mutex 是一個互斥鎖,可以建立為其他結構體的欄位;零值為解鎖狀態。Mutex 型別的鎖和執行緒無關,可以由不同的執行緒加鎖和解鎖。

type Mutex struct {
	state int32
	sema  uint32
}

2、方法

Mutex是一個互斥鎖,可以建立為其他結構體的欄位;零值為解鎖狀態。Mutex型別的鎖和執行緒無關,可以由不同的執行緒加鎖和解鎖。

Lock

func (m *Mutex) Lock()

Lock方法鎖住m,如果m已經加鎖,則阻塞直到m解鎖。

Unlock

func (m *Mutex) Unlock()

Unlock方法解鎖m,如果m未加鎖會導致執行時錯誤。鎖和協程無關,可以由不同的協程加鎖和解鎖。

注意:

  • 在一個 goroutine 獲得 Mutex 後,其他 goroutine 只能等到這個 goroutine 釋放該 Mutex
  • 使用 Lock() 加鎖後,不能再繼續對其加鎖,直到利用 Unlock() 解鎖後才能再加鎖
  • 在 Lock() 之前使用 Unlock() 會導致 panic 異常
  • 已經鎖定的 Mutex 並不與特定的 goroutine 相關聯,這樣可以利用一個 goroutine 對其加鎖,再利用其他 goroutine 對其解鎖
  • 在同一個 goroutine 中的 Mutex 解鎖之前再次進行加鎖,會導致死鎖
  • 適用於讀寫不確定,並且只有一個讀或者寫的場景

3、示例

示例一:

var mutex sync.Mutex				//互斥鎖
func printer(str string){
	mutex.Lock()				//加鎖
	defer mutex.Unlock()		//解鎖
	for _,ch:=range str{
		fmt.Printf("%c",ch)
		time.Sleep(time.Millisecond*300)
	}
}
func user1(){
	printer("hello ")
}
func user2(){
	printer("world")
}
func main() {
	go user1()
	go user2()
	for  {
		;
	}
}

輸出:

hello world

示例二:

package main

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

func main() {

    var mutex sync.Mutex
    wait := sync.WaitGroup{}

    fmt.Println("Locked")
    mutex.Lock()

    for i := 1; i <= 3; i++ {
        wait.Add(1)

        go func(i int) {
            fmt.Println("Not lock:", i)

            mutex.Lock()
            fmt.Println("Lock:", i)

            time.Sleep(time.Second)

            fmt.Println("Unlock:", i)
            mutex.Unlock()

            defer wait.Done()
        }(i)
    }

    time.Sleep(time.Second)
    fmt.Println("Unlocked")
    mutex.Unlock()

    wait.Wait()

}

輸出:

Locked
Not lock: 3
Not lock: 2
Not lock: 1
Unlocked
Lock: 3
Unlock: 3
Lock: 2
Unlock: 2
Lock: 1
Unlock: 1

4、總結

互斥鎖相互排斥,誰搶到鎖誰執行。

參考:https://shockerli.net/post/golang-pkg-mutex/

參考:https://blog.csdn.net/weixin_43851310/article/details/87890645