GoLang RW뮤텍스

Sheeraz Gul 2023년6월20일
GoLang RW뮤텍스

이 튜토리얼은 GoLang에서 rwmutex를 사용하는 방법을 보여줍니다.

GoLang RWMutex

뮤텍스는 언제든지 어떤 스레드가 변수에 액세스했는지 추적하는 데 사용되는 상호 배제의 약자입니다. 뮤텍스는 GoLang의 sync 패키지에서 제공되는 데이터 구조입니다.

뮤텍스는 Go 코드를 사용하여 동시성을 수행할 때 사용됩니다. 다음은 GoLang에서 뮤텍스를 사용하는 간단한 예입니다.

package main

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

func EvenNumber(num int) bool {
    return num%2 == 0
}

func main() {
    num := 2
    var DemoMutex sync.Mutex

    go func() {
        DemoMutex.Lock()
        defer DemoMutex.Unlock()
        EvenNum := EvenNumber(num)
        time.Sleep(5 * time.Millisecond)
        if EvenNum {
            fmt.Println("The number", num, " is even")
            return
        }
        fmt.Println("The number", num, "is odd")
    }()

    go func() {
        DemoMutex.Lock()
        num++
        DemoMutex.Unlock()
    }()

    time.Sleep(time.Second)
}

위의 코드는 숫자가 짝수인지 홀수인지 확인합니다. 여기서 동시 고루틴은 데이터를 손상시킬 수 있으므로 뮤텍스를 사용하여 손상을 방지하기 위해 데이터를 잠그고 잠금 해제합니다.

출력을 참조하십시오.

The number 2  is even

mutexRWmutex는 다릅니다. 여기서 mutex는 단순 뮤텍스이고 RWmutex는 리더-라이터 상호 배제 잠금입니다. RWMutex를 사용하면 임의의 수의 판독기 또는 한 명의 작성자가 잠금을 보유합니다.

RWMutex의 값이 0이면 잠금 해제된 뮤텍스입니다. RWMutex 뮤텍스를 사용하여 동일한 예제를 시도해 봅시다.

package main

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

func EvenNumber(num int) bool {
    return num%2 == 0
}

func main() {
    num := 2
    var DemoRWM sync.RWMutex

    // both goroutines call DemoRWM.Lock() before accessing `num` and then call the DemoRWM.Unlock after they are done
    go func() {
        DemoRWM.RLock()
        defer DemoRWM.RUnlock()
        EvenNum := EvenNumber(num)
        time.Sleep(5 * time.Millisecond)
        if EvenNum {
            fmt.Println("The number", num, " is even")
            return
        }
        fmt.Println("The number", num, "is odd")
    }()

    go func() {
        DemoRWM.Lock()
        num++
        DemoRWM.Unlock()
    }()

    time.Sleep(time.Second)
}

여기에서 볼 수 있듯이 두 고루틴num에 액세스하기 전에 DemoRWM.Lock()을 호출한 다음 완료된 후에 DemoRWM.Unlock을 호출합니다. 코드는 RWMutex를 사용합니다.

출력을 참조하십시오.

The number 2  is even

RWMutex가 모든 판독기가 동시에 데이터에 액세스할 수 있도록 허용하고 기록기가 다른 판독기를 잠그는 RWMutex에 대한 또 다른 예를 시도해 보겠습니다.

예를 참조하십시오.

package main

import (
    "fmt"
    "sync"
)

func main() {
    DemoMap := map[int]int{}

    DemoRWM := &sync.RWMutex{}

    go LoopWrite(DemoMap, DemoRWM)
    go LoopRead(DemoMap, DemoRWM)
    go LoopRead(DemoMap, DemoRWM)
    go LoopRead(DemoMap, DemoRWM)
    go LoopRead(DemoMap, DemoRWM)
    go LoopRead(DemoMap, DemoRWM)
    go LoopRead(DemoMap, DemoRWM)
    go LoopRead(DemoMap, DemoRWM)
    go LoopRead(DemoMap, DemoRWM)

    // stop the program from exiting must be killed
    StopBlock := make(chan struct{})
    <-StopBlock
}

func LoopRead(DemoMap map[int]int, DemoRWM *sync.RWMutex) {
    for {
        DemoRWM.RLock()
        for k, v := range DemoMap {
            fmt.Println(k, "-", v)
        }
        DemoRWM.RUnlock()
    }
}
func LoopWrite(DemoMap map[int]int, DemoRWM *sync.RWMutex) {
    for {
        for i := 0; i < 100; i++ {
            DemoRWM.Lock()
            DemoMap[i] = i
            DemoRWM.Unlock()
        }
    }
}

보시다시피 RWMutex를 사용하면 원하는 만큼 read를 사용할 수 있습니다. 이 코드의 출력은 다음과 같습니다.

timeout running program
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
1 - 1
작가: Sheeraz Gul
Sheeraz Gul avatar Sheeraz Gul avatar

Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.

LinkedIn Facebook