HOWTO · Go

GoLang RW뮤텍스

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

이 페이지의 내용

이 튜토리얼은 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