>백엔드 개발 >Golang >Go 언어의 잠금 메커니즘을 자세히 설명하는 기사

Go 언어의 잠금 메커니즘을 자세히 설명하는 기사

PHPz
PHPz원래의
2023-04-13 18:12:031682검색

동시성이 뛰어난 프로그래밍 언어로서 Go 언어의 동시성 제어 메커니즘은 매우 중요합니다. 가장 일반적으로 사용되는 메커니즘 중 하나는 잠금 메커니즘입니다. 이 기사에서는 Go 언어로 잠금 메커니즘을 구현하는 방법을 소개합니다.

Go 언어 잠금

Go 언어에서 가장 일반적으로 사용되는 잠금은 뮤텍스 잠금(Mutex)입니다. 뮤텍스는 공유 리소스에 대한 액세스를 제어하는 ​​데 사용되는 특수 바이너리 세마포어입니다. Go 언어는 표준 라이브러리의 "sync" 패키지를 통해 뮤텍스 잠금 기능을 제공합니다. 뮤텍스 잠금 유형은 다음과 같이 정의됩니다.

type Mutex struct {
    state int32
    sema  uint32
}

상태 필드는 잠금 상태를 기록하는 데 사용되며 sema 필드는 세마포어입니다.

뮤텍스 잠금을 사용하기 전에 Lock 메서드를 호출하여 잠금을 획득해야 합니다. 다른 코루틴이 이미 잠금을 보유하고 있는 경우 현재 코루틴은 차단되고 잠금이 해제될 때까지 기다립니다. 예:

var mu sync.Mutex
// ...
mu.Lock()
// ...
mu.Unlock()

이 코드에서 mu는 뮤텍스 잠금입니다. mu.Lock()은 잠금을 획득하는 데 사용됩니다. 다른 코루틴이 이미 잠금을 보유하고 있으면 현재 코루틴이 차단됩니다. mu.Unlock()은 잠금을 해제하는 데 사용됩니다. mu是一个互斥锁。mu.Lock()用于获取锁,如果锁已经被其他协程持有,则当前协程将会被阻塞。mu.Unlock()用于释放锁。

这个机制非常简单,但实际上效率并不高。如果有很多协程试图获取同一个互斥锁,那么处理时就很容易产生拥塞,从而使得整个程序的效率降低。

读写锁

在一些需要进行读写操作的场景下,互斥锁的效率很低。因为互斥锁只能保证在同一时刻只有一个协程能够访问共享资源,读操作和写操作都需要先等待锁的释放。但是,如果只有读操作,则这种等待并没有必要。因为多个协程可以同时对同一个资源进行读操作,而不会对数据产生破坏性的修改。

这时候就需要用到读写锁(RWMutex)。读写锁是一种特殊的互斥锁。一个资源可以被多个协程同时进行读操作,但只能被一个协程进行写操作。因此,在写操作时,所有读操作将会被阻塞,等待写操作结束。读写锁的类型定义如下:

type RWMutex struct {
    w           Mutex // 用于写操作的互斥锁
    writerSem   uint32
    readerSem   uint32
    readerCount int32  // 当前进行读操作的协程数量
    readerWait  int32  // 等待读操作的协程数量
}

读写锁有两种状态:读锁和写锁。读锁状态下,多个协程可以同时进行读操作;写锁状态下,只有一个协程可以进行写操作。同时,读写锁支持协程优先级的机制,这意味着等待时间更长的协程将会首先获取到锁。

获取读锁的方法是RLock(),释放读锁的方法是RUnlock();获取写锁的方法是Lock(),释放写锁的方法是Unlock()。举个例子:

var rw sync.RWMutex
// ...
func read() {
    rw.RLock()
    // ...
    rw.RUnlock()
}
// ...
func write() {
    rw.Lock()
    // ...
    rw.Unlock()
}

这段代码演示了如何在Go语言中使用读写锁。read()函数获取了读锁,同时可以被多个协程同时调用;而write()

이 메커니즘은 매우 간단하지만 실제로는 그리 효율적이지 않습니다. 동일한 뮤텍스를 얻으려는 코루틴이 많으면 처리 중에 혼잡이 쉽게 발생하여 전체 프로그램의 효율성이 저하됩니다.

읽기-쓰기 잠금

읽기 및 쓰기 작업이 필요한 일부 시나리오에서는 뮤텍스 잠금의 효율성이 매우 낮습니다. 뮤텍스 잠금은 동시에 하나의 코루틴만 공유 리소스에 액세스할 수 있도록 보장할 수 있으므로 읽기 및 쓰기 작업 모두 잠금이 먼저 해제될 때까지 기다려야 합니다. 그러나 읽기 작업만 있는 경우에는 이 대기가 필요하지 않습니다. 여러 코루틴이 데이터를 파괴적으로 수정하지 않고도 동일한 리소스를 동시에 읽을 수 있기 때문입니다.

이때 읽기-쓰기 잠금(RWMutex)을 사용해야 합니다. 읽기-쓰기 잠금은 상호 배제 잠금의 특별한 유형입니다. 리소스는 동시에 여러 코루틴에서 읽을 수 있지만 쓰기는 하나의 코루틴에서만 가능합니다. 따라서 쓰기 작업 중에는 모든 읽기 작업이 차단되고 쓰기 작업이 완료될 때까지 기다립니다. 읽기-쓰기 잠금 유형은 다음과 같이 정의됩니다.

func singleton() {
    var once sync.Once
    once.Do(func() {
        // 初始化对象
    })
    // 使用对象
}
읽기-쓰기 잠금에는 읽기 잠금과 쓰기 잠금의 두 가지 상태가 있습니다. 읽기 잠금 상태에서는 여러 코루틴이 동시에 읽기 작업을 수행할 수 있으며, 쓰기 잠금 상태에서는 하나의 코루틴만 쓰기 작업을 수행할 수 있습니다. 동시에 읽기-쓰기 잠금은 코루틴 우선순위 메커니즘을 지원합니다. 즉, 더 오래 기다리는 코루틴이 먼저 잠금을 획득합니다.

읽기 잠금을 획득하는 방법은 RLock()이고, 읽기 잠금을 해제하는 방법은 RUnlock()입니다. 쓰기 잠금을 획득하는 방법은 입니다. >Lock()code>, 쓰기 잠금을 해제하는 방법은 Unlock()입니다. 예: 🎜rrreee🎜이 코드는 Go 언어에서 읽기-쓰기 잠금을 사용하는 방법을 보여줍니다. read() 함수는 읽기 잠금을 획득하고 동시에 여러 코루틴에서 호출할 수 있는 반면, write() 함수는 쓰기 잠금을 획득하고 하나만 가질 수 있습니다. 동시에 코루틴이 호출합니다. 🎜🎜sync.Once🎜🎜sync.Once는 매우 유용한 잠금 장치입니다. 초기화 작업은 한 번만 수행합니다. Once 내부에는 Boolean 값이 있습니다. 잠겨 있으면 호출이 실패하면 후속 호출이 즉시 반환되고 초기화가 다시 실행되지 않습니다. 🎜rrreee🎜sync.Once를 사용하면 여러 코루틴에서 반복되는 초기화 작업을 피할 수 있습니다. 🎜🎜요약🎜🎜Go 언어에서는 다중 스레드 동시성 제어를 구현하는 메커니즘이 매우 중요합니다. 뮤텍스 잠금, 읽기-쓰기 잠금 및 Once와 같은 메커니즘을 사용하면 동시 작업을 처리할 때 프로그램이 더욱 효율적이고 안전해질 수 있습니다. 실제로는 특정 시나리오에 따라 다양한 메커니즘을 선택해야 하며 선택 및 사용 전에 특정 테스트와 검증을 수행해야 합니다. 🎜

위 내용은 Go 언어의 잠금 메커니즘을 자세히 설명하는 기사의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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