>  기사  >  백엔드 개발  >  Go 언어는 잠금을 지원하나요?

Go 언어는 잠금을 지원하나요?

青灯夜游
青灯夜游원래의
2022-12-06 18:32:225704검색

Go 언어는 잠금을 지원합니다. Go 언어 표준 라이브러리는 두 가지 유형의 잠금을 제공합니다. 1. 동시 작업으로 인해 발생하는 충돌로부터 리소스를 보호할 수 있는 뮤텍스 잠금(sync.Mutex) 2. 읽기-쓰기 잠금(sync.RWMutex) 읽기 잠금이 설정되면 쓰기는 차단되지만 읽기는 차단되지 않습니다. 읽기는 많고 쓰기는 적은 환경에서는 읽기-쓰기 뮤텍스를 먼저 사용할 수 있습니다.

Go 언어는 잠금을 지원하나요?

이 튜토리얼의 운영 환경: Windows 7 시스템, GO 버전 1.18, Dell G3 컴퓨터.

go 언어 표준 라이브러리는 두 개의 잠금을 제공합니다. 하나는 뮤텍스 잠금이고 다른 하나는 읽기-쓰기 잠금입니다. Go 언어 패키지의 동기화 패키지는 뮤텍스 잠금(sync.Mutex)과 읽기-쓰기 잠금(sync.RWMutex)이라는 두 가지 잠금 유형을 제공합니다.

Mutex는 가장 간단한 잠금 유형이며 상대적으로 폭력적이기도 합니다. 고루틴이 Mutex를 획득하면 다른 고루틴은 고루틴이 Mutex를 해제할 때까지만 기다릴 수 있습니다.

RWMutex는 상대적으로 친숙하며 전형적인 write-once-read-many 모델입니다. 읽기 잠금이 사용되면 쓰기는 차단되지만 읽기는 차단되지 않습니다. 즉, 쓰기 잠금(Lock 호출)이 진행되는 동안 여러 고루틴이 동시에 읽기 잠금을 획득할 수 있습니다. () 메서드)는 다른 고루틴(읽기 또는 쓰기 여부에 관계없이)이 들어오는 것을 방지하며 전체 잠금은 고루틴이 독점적으로 소유하는 것과 같습니다. RWMutex의 구현으로 판단하면 RWMutex 유형은 실제로 Mutex를 결합합니다.

type RWMutex struct {
    w Mutex
    writerSem uint32
    readerSem uint32
    readerCount int32
    readerWait int32
}

이 두 잠금 유형의 경우 Lock() 또는 RLock()은 해당 Unlock() 또는 RUnlock() 호출이 있는지 확인해야 합니다. 그렇지 않으면 다음과 같습니다. 잠금을 기다리는 모든 고루틴이 고갈되거나 교착 상태가 발생할 수도 있습니다. [관련 권장사항: Go 비디오 튜토리얼, Programming Teaching]

lock의 일반적인 사용 패턴은 다음과 같습니다.

package main
import (
    "fmt"
    "sync"
)
var (
    // 逻辑中使用的某个变量
    count int
    // 与变量对应的使用互斥锁
    countGuard sync.Mutex
)
func GetCount() int {
    // 锁定
    countGuard.Lock()
    // 在函数退出时解除锁定
    defer countGuard.Unlock()
    return count
}
func SetCount(c int) {
    countGuard.Lock()
    count = c
    countGuard.Unlock()
}
func main() {
    // 可以进行并发安全的设置
    SetCount(1)
    // 可以进行并发安全的获取
    fmt.Println(GetCount())
}

코드 설명은 다음과 같습니다.

  • 10행은 a에서 사용되는 변수입니다. 패키지 수준 변수인지 구조 멤버 필드인지는 중요하지 않습니다.

  • 라인 13에서는 일반적으로 공유 액세스에 대한 대기 시간을 줄이기 위해 뮤텍스의 세분성을 최대한 작게 설정하는 것이 좋습니다. 여기서 저자는 습관적으로 뮤텍스 변수의 이름을

变量名+Guard

형식으로 지정하여 뮤텍스가 이 변수를 보호하는 데 사용됨을 나타냅니다.

  • 라인 16은 count 값을 얻기 위한 함수 캡슐화입니다. 이 함수를 통해 변수 count에 동시에 안전하게 액세스할 수 있습니다.

  • 라인 19에서 countGuard 뮤텍스를 잠그려고 합니다. countGuard가 잠긴 후 다른 고루틴이 계속 잠금을 시도하면 countGuard가 잠금 해제될 때까지 차단됩니다.

  • 라인 22는 defer를 사용하여 countGuard의 잠금 해제 호출을 지연시킵니다. 잠금 해제 작업은 GetCount() 함수가 반환될 때 발생합니다.

  • 라인 27에서 카운트 값을 설정할 때 countGuard는 카운트 값을 수정하는 프로세스가 원자 프로세스이고 동시 액세스 충돌이 발생하지 않도록 잠금 및 잠금 해제 작업을 수행하는 데에도 사용됩니다.

읽는 일이 많고 쓰는 일이 적은 환경에서는 뮤텍스보다 효율적인 읽기-쓰기 뮤텍스(sync.RWMutex)를 우선적으로 사용할 수 있습니다. 동기화 패키지의 RWMutex는 읽기-쓰기 뮤텍스의 캡슐화를 제공합니다.

뮤텍스 예시의 코드 일부를 읽기-쓰기 뮤텍스로 수정했습니다. 아래 코드를 참조하세요.

var (
    // 逻辑中使用的某个变量
    count int
    // 与变量对应的使用互斥锁
    countGuard sync.RWMutex
)
func GetCount() int {
    // 锁定
    countGuard.RLock()
    // 在函数退出时解除锁定
    defer countGuard.RUnlock()
    return count
}

코드 설명은 다음과 같습니다.

  • line 6, countGuard 선언 시, sync.Mutex 뮤텍스에서 잠금이 sync.RWMutex 읽기-쓰기 뮤텍스 잠금으로 변경됩니다.

  • 라인 12에서 개수를 얻는 프로세스는 개수 데이터를 읽는 프로세스로, 읽기 및 쓰기 뮤텍스 잠금에 적합합니다. 이 줄에서 countGuard.Lock()을 countGuard.RLock()으로 대체하여 읽기-쓰기 뮤텍스를 읽음으로 표시합니다. 다른 고루틴이 동시에 countGuard에 액세스하고 countGuard.RLock()을 호출하면 차단이 발생하지 않습니다.

  • 읽기 모드 잠금에 해당하는 15행은 읽기 모드를 사용하여 잠금을 해제합니다.

특별 참고 사항:

  • sync.Mutex의 잠금은 중첩될 수 없습니다.

  • sync.RWMutex의 RLock()은 중첩될 수 있습니다.

  • sync.RWMutex mu.Lock()은 중첩될 수 없습니다.

  • sync.RWMutex의
  • mu.Lock()은 mu.RLock()

더 많은 프로그래밍 관련 지식을 보려면 프로그래밍 비디오 를 방문하세요! !

위 내용은 Go 언어는 잠금을 지원하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.