Go 언어Java와 다른 언어에 비해 큰 장점은 동시성 프로그램을 쉽게 작성할 수 있다는 것입니다. Go 언어에는 고루틴 메커니즘이 내장되어 있습니다. 고루틴을 사용하면 동시 프로그램을 빠르게 개발하고 멀티 코어 프로세서 리소스를 더 잘 활용할 수 있습니다. 이 글에서는 고루틴의 적용과 스케줄링 구현에 대해 배웁니다.
1. Go 언어의 동시성 지원
고루틴 프로그래밍 사용(권장: go 비디오 튜토리얼)
go 키워드를 사용하여 고루틴을 생성하세요. 호출해야 하는 함수 앞에 go 선언을 두고, 동일한 주소 공간에서 함수를 호출하고 실행하면 해당 함수가 독립적인 동시 스레드로 실행됩니다. 이런 종류의 스레드를 Go 언어에서는 고루틴(goroutine)이라고 합니다.
고루틴의 사용법은 다음과 같습니다.
//go 关键字放在方法调用前新建一个 goroutine 并执行方法体 go GetThingDone(param1, param2); //新建一个匿名方法并执行 go func(param1, param2) { }(val1, val2) //直接新建一个 goroutine 并在 goroutine 中执行代码块 go { //do someting... }
고루틴은 멀티코어 CPU 환경에서 병렬이기 때문입니다. 코드 블록이 여러 고루틴에서 실행되면 코드 병렬성이 달성됩니다.
프로그램 실행을 알아야 하는 경우 병렬 결과를 얻는 방법은 무엇입니까? 채널과 함께 사용해야 합니다.
채널을 사용하여 동시성 제어
채널은 동시에 실행되는 기능을 동기화하고 일종의 값 전달 통신 메커니즘을 제공하는 데 사용됩니다.
채널을 통과하는 요소 유형, 컨테이너(또는 버퍼) 및 전송 방향은 "<-" 연산자로 지정됩니다.
내장 함수 make를 사용하여 채널을 할당할 수 있습니다:
i := make(chan int) // by default the capacity is 0 s := make(chan string, 3) // non-zero capacity r := make(<-chan bool) // can only read from w := make(chan<- []os.FileInfo) // can only write to
런타임 구성.GOMAXPROCS
다음 코드를 사용하여 동시 작업을 수행하기 위해 멀티 코어를 사용할지 여부를 명시적으로 설정할 수 있습니다.
runtime.GOMAXPROCS()
숫자 GOMAXPROCS는 작업량에 따라 할당됩니다. 예, 하지만 CPU 코어 수보다 커서는 안 됩니다.
병렬 실행 구성은 CPU 집약적이고 병렬이 많은 시나리오에 더 적합합니다. IO 집약적인 경우 다중 코어를 사용하면 CPU 전환으로 인한 성능 손실이 증가합니다.
이제 Go 언어의 동시성 메커니즘을 이해했으니, 고루틴 메커니즘의 구체적인 구현을 살펴보겠습니다.
2. 병렬성과 동시성의 차이
프로세스, 스레드 및 프로세서
현대 운영 체제에서 스레드는 프로세서 스케줄링 및 할당의 기본 단위이고 프로세스는 리소스의 기본 단위입니다. 소유권. 각 프로세스는 개인 가상 주소 공간, 코드, 데이터 및 기타 다양한 시스템 리소스로 구성됩니다. 스레드는 프로세스 내의 실행 단위입니다. 각 프로세스에는 사용자가 직접 생성할 필요는 없지만 시스템에서 자동으로 생성되는 하나 이상의 기본 실행 스레드가 있습니다. 사용자는 필요에 따라 애플리케이션에서 다른 스레드를 생성하고 여러 스레드가 동일한 프로세스에서 동시에 실행됩니다.
병렬성과 동시성
동시성과 병렬성은 서로 다른 개념입니다. 멀티스레딩 모델을 이해하려면 이를 이해하는 것이 매우 중요합니다.
프로그램의 동시성이나 병렬성을 설명할 때는 프로세스나 스레드의 관점에서 기술해야 합니다.
동시성: 특정 기간에 실행되는 스레드 또는 프로세스는 많지만 어느 시점에서는 하나만 실행됩니다. 여러 스레드 또는 프로세스가 시간 분할을 위해 경쟁하고 차례로 실행됩니다.
병렬: 기간 및 한 지점 시간 여러 스레드나 프로세스가 실행 중입니다. 비동시 프로그램에는 언제든지 하나의 수직 제어 로직만 있습니다. 즉, 프로그램은 이 제어 로직의 특정 위치, 즉 순차적 실행에만 있습니다. 프로그램이 특정 시간에 동시에 여러 CPU 파이프라인에 의해 처리되면 프로그램이 병렬로 실행되고 있다고 말합니다.
병렬에는 하드웨어 지원이 필요합니다. 단일 코어 프로세서는 동시 작업만 수행할 수 있는 반면, 다중 코어 프로세서는 병렬 실행을 수행할 수 있습니다.
동시성은 병렬성의 필수 조건입니다. 프로그램 자체가 동시성이 아닌 경우, 즉 논리적 실행 시퀀스가 하나만 있는 경우 병렬 처리를 허용할 수 없습니다.
동시성은 병렬성의 충분조건이 아닙니다. 동시 프로그램이 하나의 CPU에서만 처리된다면(시간 공유를 통해) 병렬이 아닙니다.
예를 들어, "Hello World"를 출력하는 가장 간단한 순차 구조 프로그램을 작성합니다. 프로그램에 여러 스레드를 추가하고 각 스레드가 "Hello World"를 인쇄하는 경우 프로그램은 동시입니다. 런타임 중에 이 프로그램에 단일 CPU만 할당된 경우 이 동시 프로그램은 아직 병렬이 아니며 프로그램 병렬성을 달성하려면 다중 코어 프로세서에 배포해야 합니다.
3. 여러 가지 멀티 스레딩 모델
사용자 스레드와 커널 수준 스레드스레드 구현은 사용자 수준 스레드(사용자 수준 스레드, ULT)와 두 가지 범주로 나눌 수 있습니다. 커널 수준 스레드(Kemel-LevelThread, KLT). 사용자 스레드는 사용자 코드의 지원을 받고, 커널 스레드는 운영 체제 커널의 지원을 받습니다.
멀티 스레딩 모델멀티 스레딩 모델은 사용자 수준 스레드와 커널 수준 스레드의 연결 방법이 다릅니다.
(1) 다대일 모델(M:1)
여러 사용자 수준 스레드를 하나의 커널 수준 스레드로 매핑하고 스레드 관리는 사용자 공간에서 완료됩니다. 이 모드에서는 사용자 수준 스레드가 운영 체제에 보이지 않습니다(즉, 투명합니다).
장점: 이 모델의 장점은 스레드 컨텍스트 전환이 사용자 공간에서 발생하여 모드 전환을 방지하여 성능에 긍정적인 영향을 미친다는 것입니다.
단점: 모든 스레드는 하나의 커널 스케줄링 엔터티, 즉 커널 스레드를 기반으로 합니다. 즉, 이는 다중 프로세서 환경에서는 허용되지 않습니다. , 그러나 병렬성 문제는 해결되지 않습니다. 스레드가 I/O 작업으로 인해 커널 상태에 빠지고 커널 상태 스레드가 I/O 데이터를 기다리는 경우 모든 스레드가 차단됩니다. 사용자 공간도 비차단 I/O를 사용할 수 있지만 성능과 복잡성이 증가합니다. 학위 문제는 피할 수 없다.
(2) 일대일 모델(1:1)
은 각 사용자 수준 스레드를 커널 수준 스레드에 매핑합니다.
각 스레드는 커널 스케줄러에 의해 독립적으로 예약되므로 한 스레드가 차단되어도 다른 스레드에는 영향을 미치지 않습니다.
장점: 멀티 코어 프로세서 하드웨어 지원으로 커널 공간 스레드 모델은 하나의 스레드가 차단되면 다른 스레드가 계속 실행될 수 있으므로 동시성 기능이 강력합니다.
단점: 사용자 수준 스레드를 생성할 때마다 해당 커널 수준 스레드를 생성해야 합니다. 이로 인해 상대적으로 높은 오버헤드가 발생하고 애플리케이션 성능에 영향을 미칩니다.
(3) 다대다 모델(M:N)
커널 스레드와 사용자 스레드의 수 비율은 M:N입니다. 커널 사용자 공간은 처음 두 가지의 장점을 결합합니다.
이 모델에서는 상호 운용을 위해 커널 스레드 스케줄러와 사용자 공간 스레드 스케줄러가 필요합니다. 기본적으로 여러 스레드가 여러 커널 스레드에 바인딩되므로 대부분의 스레드 컨텍스트 전환이 사용자 공간과 여러 코어 스레드에서 발생합니다. 프로세서 리소스를 완전히 활용할 수 있습니다.
4. 고루틴 메커니즘 구현 예약
고루틴 메커니즘은 M:N 스레드 모델을 구현합니다. Golang의 내장 스케줄러는 멀티 코어 CPU가 각 CPU를 실행하도록 허용합니다. 코루틴 하나.
고루틴 메커니즘의 원리를 이해하려면 Go 언어 스케줄러의 구현을 이해하는 것이 핵심입니다.
스케줄러 작동 방식
Go 언어에는 전체 스케줄러 구현을 지원하는 네 가지 중요한 구조, 즉 M, G, P 및 Sched가 있습니다. 처음 세 개는 Runtime.h에 정의되고 Sched는 정의됩니다. proc.c에서
Sched 구조는 M과 G 및 스케줄러의 일부 상태 정보를 저장하는 대기열을 유지 관리하는 스케줄러입니다.
M 구조는 운영 체제에서 관리하는 시스템 스레드인 Machine입니다. M은 M에서 실행되는 작은 개체 메모리 캐시(mcache), 현재 실행 중인 고루틴 및 난수 생성기를 유지하는 대규모 구조입니다. 그리고 많은 정보.
P 구조는 프로세서, 프로세서입니다. 주요 목적은 고루틴 대기열, 즉 실행 대기열을 유지하는 것입니다. 프로세서는 N:1 스케줄링에서 M:N 스케줄링으로 전환하는 데 중요한 부분입니다.
G는 고루틴 구현의 핵심 구조입니다. 여기에는 스택, 명령어 포인터 및 차단된 채널과 같이 고루틴 예약에 중요한 기타 정보가 포함되어 있습니다.
프로세서 수는 시작 시 환경 변수 GOMAXPROCS의 값으로 설정되거나 런타임 시 GOMAXPROCS() 함수를 호출하여 설정됩니다. 프로세서 수가 고정되어 있다는 것은 GOMAXPROCS 스레드만 언제든지 go 코드를 실행하고 있음을 의미합니다.
저희는 머신 프로세서와 고루틴을 각각 삼각형, 직사각형, 원으로 표현합니다.
단일 코어 프로세서의 시나리오에서는 모든 고루틴이 동일한 M 시스템 스레드에서 실행됩니다. 각 M 시스템 스레드는 언제든지 프로세서에 하나의 고루틴만 있고 다른 고루틴은 다음과 같습니다. 실행 대기열에서 기다리고 있습니다. 고루틴은 자체 타임 슬라이스 실행을 마친 후 컨텍스트를 포기하고 실행 대기열로 돌아갑니다. 멀티 코어 프로세서 시나리오에서 고루틴을 실행하기 위해 각 M 시스템 스레드는 프로세서를 보유합니다.
일반적인 상황에서는 스케줄러가 위 프로세스에 따라 일정을 예약하지만 스레드가 차단됩니다. goroutine의 스레드 차단 처리를 살펴보세요.
스레드 차단
시스템 호출 등 실행 중인 고루틴이 차단되면 현재 M 스레드는 프로세서를 포기하고 P는 새 스레드로 전송됩니다. 달리다.
runqueue 실행이 완료되었습니다
한 프로세서의 runqueue가 비어 있으면 예약할 고루틴이 없습니다. 이는 다른 컨텍스트에서 고루틴의 절반을 훔칠 것입니다.
5. 동시성 구현에 대한 추가 생각
Go 언어와 Scala 동시성 구현의 차이점, Golang CSP와 Golang CSP의 비교 등 Go 언어의 동시성 메커니즘에 대해 논의할 가치가 있는 것들이 많습니다. 배우 모델 등
이러한 동시성 메커니즘 구현을 이해하면 동시성 프로그램을 더 잘 개발하고 성능을 최적화하는 데 도움이 될 수 있습니다.
세 가지 멀티스레딩 모델과 관련하여 Java 언어의 구현에 주목할 수 있습니다.
Java는 JVM을 통해 기본 운영 체제의 차이점을 캡슐화하며, 서로 다른 운영 체제는 서로 다른 스레딩 모델을 사용할 수 있다는 것을 알고 있습니다. 예를 들어 Linux와 Windows는 일대일 모델을 사용할 수 있고 일부 버전의 Solaris 및 유닉스는 다대다 모델을 사용할 수 있습니다. JVM 사양은 멀티스레딩 모델의 특정 구현을 규정하지 않습니다. 1:1(커널 스레드), N:1(사용자 상태 스레드) 및 M:N(혼합) 모델이 허용됩니다. Java 언어의 멀티스레딩 모델의 경우 특정 JVM에 대해 구현해야 합니다. 예를 들어 Oracle/Sun의 HotSpot VM은 기본적으로 1:1 스레딩 모델을 사용합니다.
위 내용은 Go 언어 동시성 메커니즘에 대한 자세한 그래픽 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!