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
mutex와 RWmutex는 다릅니다. 여기서 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