Go 언어에서 동시성 제어를 구현하는 방법: 1. 여러 고루틴의 작업 처리에는 종속성 또는 연결 관계가 있습니다. 2. 채널에서는 여러 그루틴의 데이터 전송을 적극적으로 취소할 수 있습니다. Context의 기능을 충족합니다. 3. 컨텍스트, 메타데이터 전파, 신호 전파 취소, 시간 초과 제어 등을 포함한 다중 레벨 그루틴 간의 신호 전파.
이 기사의 운영 환경: Windows 10 시스템, go1.20 버전, dell g3 컴퓨터.
Golang에서는 go 키워드를 통해 고루틴을 열 수 있으므로 Go에서 동시 코드를 쉽게 작성할 수 있습니다. 그러나 동시에 실행되는 그루틴을 효과적으로 제어하는 방법은 무엇입니까?
동시성 제어에 관해 많은 사람들이 먼저 잠금을 생각할 수 있습니다. Golang은 또한 mutex lock sync.Mutex 및 읽기-쓰기 잠금 sync.RWMutex를 포함한 잠금 관련 메커니즘을 제공합니다. 잠금 외에도 원자적 작업인 동기화/원자성 등도 있습니다. 그러나 이러한 메커니즘의 초점은 고루틴의 동시 데이터 안전성입니다. 이 기사에서 논의하고 싶은 것은 고루틴의 동시성 동작 제어입니다.
고루틴 동시 동작 제어에는 WaitGroup, 채널 및 컨텍스트라는 세 가지 일반적인 방법이 있습니다.
WaitGroup은 sync 패키지 하위에 있으며, 사용법은 다음과 같습니다.
func main() { var wg sync.WaitGroup wg.Add(2) //添加需要完成的工作量2 go func() { wg.Done() //完成工作量1 fmt.Println("goroutine 1 完成工作!") }() go func() { wg.Done() //完成工作量1 fmt.Println("goroutine 2 完成工作!") }() wg.Wait() //等待工作量2均完成 fmt.Println("所有的goroutine均已完成工作!")}输出: //goroutine 2 完成工作! //goroutine 1 完成工作! //所有的goroutine均已完成工作!
WaitGroup 이 동시성 제어 방법은 특정 작업에 여러 고루틴이 함께 작동해야 하는 상황에 특히 적합하며, 각 고루틴은 작업의 일부만 수행할 수 있으며 모든 고루틴이 완료될 때만 작업이 완료됩니다. 그러므로 WaitGroup은 기다림의 방식이라는 이름과 같은 의미를 갖고 있습니다.
그러나 실제 비즈니스에는 시나리오가 있습니다. 특정 요구 사항이 충족되면 특정 고루틴이 종료되도록 적극적으로 알려야 합니다. 예를 들어, 백그라운드 모니터링 고루틴을 시작하면 모니터링이 더 이상 필요하지 않을 때 모니터링 고루틴에 종료를 알려야 합니다. 그렇지 않으면 계속 유휴 상태가 되어 누출이 발생하게 됩니다.
위의 시나리오에서 WaitGroup은 무력합니다. 생각할 수 있는 가장 간단한 방법은 전역 변수를 정의하고 이 변수를 다른 곳에서 수정하여 이를 알리는 것입니다. 백그라운드 고루틴은 이 변수가 변경된 것을 발견하면 자체적으로 닫힙니다. 다소 번거롭습니다. 이 경우 채널+선택이 유용할 수 있습니다.
func main() { exit := make(chan bool) go func() { for { select { case <-exit: fmt.Println("退出监控") return default: fmt.Println("监控中") time.Sleep(2 * time.Second) } } }() time.Sleep(5 * time.Second) fmt.Println("通知监控退出") exit <- true //防止main goroutine过早退出 time.Sleep(5 * time.Second)}输出: //监控中 //监控中 //监控中 //通知监控退出 //退出监控
이 채널+선택 조합은 고루틴 종료를 알리는 더 우아한 방법입니다.
그러나 이 솔루션에도 한계가 있습니다. 상상해 보세요. 종료하기 위해 모두 제어해야 하는 고루틴이 여러 개 있다면 어떻게 될까요? 이 고루틴이 다른 고루틴을 생성하면 어떻게 될까요? 물론 이 문제를 해결하기 위해 많은 채널을 정의할 수 있지만 고루틴의 관계 체인은 이 시나리오를 복잡하게 만듭니다.
위의 시나리오는 CS 아키텍처 모델에서 일반적입니다. Go에서는 일련의 요청을 처리하기 위해 각 클라이언트에 대해 별도의 고루틴(A)이 열리는 경우가 많으며, 종종 단일 A가 다른 서비스도 요청하고(다른 고루틴 B 시작) B도 다른 고루틴 C, C를 요청할 수 있습니다. 예를 들어 Databse 서버로 요청을 보냅니다. 클라이언트의 연결이 끊어지면 시스템이 A, B, C가 차지한 리소스를 회수하기 전에 클라이언트와 연결된 A, B, C가 즉시 종료되어야 한다고 상상해 보세요. A를 종료하는 것은 간단하지만 B와 C도 종료하도록 알리는 방법은 무엇입니까?
이때 Context가 나타납니다.
func A(ctx context.Context, name string) { go B(ctx ,name) //A调用了B for { select { case <-ctx.Done(): fmt.Println(name, "A退出") return default: fmt.Println(name, "A do something") time.Sleep(2 * time.Second) } }}func B(ctx context.Context, name string) { for { select { case <-ctx.Done(): fmt.Println(name, "B退出") return default: fmt.Println(name, "B do something") time.Sleep(2 * time.Second) } }}func main() { ctx, cancel := context.WithCancel(context.Background()) go A(ctx, "【请求1】") //模拟client来了1个连接请求 time.Sleep(3 * time.Second) fmt.Println("client断开连接,通知对应处理client请求的A,B退出") cancel() //假设满足某条件client断开了连接,那么就传播取消信号,ctx.Done()中得到取消信号 time.Sleep(3 * time.Second)}输出: //【请求1】 A do something //【请求1】 B do something //【请求1】 A do something //【请求1】 B do something //client断开连接,通知对应处理client请求的A,B退出 //【请求1】 B退出 //【请求1】 A退出
예제에서는 클라이언트에서 연결 요청이 시뮬레이션되고 이에 따라 Goroutine A가 열리고 A와 B 모두 취소 기능을 사용하여 추적할 수 있습니다. , 이 두 개의 모든 고루틴이 종료됩니다.
이것은 컨트롤러와 같습니다. 스위치를 누르면 이 컨텍스트를 기반으로 하거나 파생된 모든 하위 컨텍스트가 이때 정리 작업을 수행할 수 있으며 고루틴이 수행됩니다. 드디어 출시되었습니다. 이것은 시작 후 제어할 수 없는 고루틴 문제를 우아하게 해결합니다.
Context의 자세한 사용법은 이 문서의 범위를 벗어납니다. Context 패키지를 구체적으로 설명하는 후속 기사가 있을 예정이므로 계속 지켜봐 주시기 바랍니다.
이 문서에는 Golang의 세 가지 동시성 동작 제어 모드가 나열되어 있습니다. 모드 간에는 좋고 나쁨의 차이가 없으며 단지 다양한 시나리오에 적합한 솔루션을 사용하는 것에 달려 있습니다. 실제 프로젝트에서는 여러 가지 방법을 조합하여 사용하는 경우가 많습니다.
Golang에서는 go 키워드를 통해 고루틴을 열 수 있으므로 Go에서 동시 코드를 쉽게 작성할 수 있습니다. 그러나 동시에 실행되는 그루틴을 효과적으로 제어하는 방법은 무엇입니까?
동시성 제어에 관해 많은 사람들이 먼저 잠금을 생각할 수 있습니다. Golang은 또한 mutex lock sync.Mutex 및 읽기-쓰기 잠금 sync.RWMutex를 포함한 잠금 관련 메커니즘을 제공합니다. 잠금 외에도 원자적 작업인 동기화/원자성 등도 있습니다. 그러나 이러한 메커니즘의 초점은 고루틴의 동시 데이터 안전성입니다. 이 기사에서 논의하고 싶은 것은 고루틴의 동시성 동작 제어입니다.
고루틴 동시 동작 제어에는 WaitGroup, 채널 및 컨텍스트라는 세 가지 일반적인 방법이 있습니다.
위 내용은 Go 언어로 동시성 제어를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!