2017-10-08 1 views
2

이동 문서는 말한다 :goroutine이 차단 된 경우 실행 시간을 확인하는 방법은 무엇입니까?

그들이 원 때문에 이러한 차단 시스템 호출을 호출하여 같은 코 루틴 블록, 실행시 자동으로 다른, 실행 가능한 스레드로 동일한 운영 체제 스레드에서 다른 코 루틴으로 이동 차단되지 않습니다.

그러나 런타임시 goroutine이 차단되는 것을 어떻게 감지합니까?

예를 들어 go-routine 중 하나에서 계산을 실행하면 차단 작업으로 평가됩니까?

package main 

import (
    "fmt" 
    "runtime" 
) 

func f(from string, score int) { 
    for i := 0; i < score; i++ { 
      for z := 0; z < score; z++ { 
     } 
    } 

    fmt.Println(from, " Done") 
} 

func main() { 
runtime.GOMAXPROCS(1) 
f("direct", 300000) 
go f("foo", 200000) 
go f("bar", 20000) 
go f("baz", 2000) 

go func(msg string) { 
     fmt.Println(msg) 
    }("going without loop") 

     var input string 
    fmt.Scanln(&input) 
    fmt.Println("done") 
} 

나는 결과를 얻고있다 : baz, boo bar. 하지만 왜? foo이 (가) 차단 중이라는 것을 알게 되나요?

+0

http://blog.alexnesterov.com/post/coroutines-part-1/ 또한 재미있는 읽을 거리입니다 (Kotlin에 대해서는 Go라고도 함) – VonC

답변

1

이 티켓이 질문에 관련 :

https://github.com/golang/go/issues/11462

각 차단이 런타임에 의해 제공됩니다, 당신은 할 수 호출합니다. 따라서 런타임은 차단 될 수있는 일이 발생했는지를 안다. 예를 들어

: 당신이 sync.MutexLock()를 호출 할 경우

  1. 런타임은 그 차단 여부 및 그에 따라 행동 할 어떠했는지 검사를 처리합니다.

  2. exec.CmdRun() 또는 Output() (또는 이와 비슷한)을 호출하면 런타임 호출시이를 통보하고이 호출이 차단됩니다. 실행중인 프로그램이 차단된다는 것을 알 수 없기 때문에 최악의 상황을 가정해야합니다.

내가 알고있는 한, goroutine이 차단할 수있는 방법과 각 예제에 대한 예가 두 가지 원리 메커니즘이 있습니다.

  1. "외부"도움말없이 런타임에서 제공하는 것들의 예입니다.

  2. syscall이 관련된 것들의 예입니다. Golang은 예를 들어 gnu libc를 사용하지 않고 os를 호출하여 직접 필요한 시스템 호출을 구현합니다.이 모든 호출은 패키지 syscall (최선을 다해서)을 거치며 여기에는 런타임에 어떤 일이 발생했는지 통보받을 수있는 단일 훅이 있습니다.

    사진이 될 수도로 조금 흐리 물론

는, 그 golang 크로스 OS 스레드 동기화도 1.의 운영 체제에서 뮤텍스가 필요하고 어떻게 든도 예 2

의 비트입니다

질문에 대한 코드에 대해 : Go는 컴파일러가 루프를 최적화하지 않은 경우 f가 많은 시간을 필요로한다는 것을 이해하지 못합니다. 그런 엄격한 루프에서 go 스케줄러는 goroutine을 "중지"할 수 없으며 루프에 선점 포인트가 없으므로 다른 스케줄을 실행으로 설정할 수 없습니다. 그래서 만약 당신이 여러 개의 goroutines을 여러 개의 꽉 루프를 수행 선매 포인트없이, 그들은 당신의 CPU를 먹을 수도 있고 다른 모든 goroutines 기다려야 할 때까지 적어도 하나의 긴밀한 루프가 완료됩니다. 그러나 해당 루프에서 다른 함수를 호출하면 해당 그림이 변경되고 함수 호출로 이 선점됩니다. 코멘트에 요청

user1432751 :

작업이 일어날 것입니다 차단하면 CPU 레지스터와 무슨

? 현재 스레드가 goroutines에 의해 차단되고 있습니다. Go scheduler가 새로운 시스템 스레드를 만들고 거기에 다른 스레드를 모두 마이 그 레이션 하시겠습니까? -

go 일정은 선점 적이 지 않습니다 (적어도 내가 마지막으로 확인한 상태 였지만). 특정 선점 지점에서 일정을 잡았습니다. 예를 들어, syscalls, 채널에서 전송 및 대기하고 올바르게 함수 호출을 기억하는지 확인하십시오. 따라서 그 지점에서 내부 함수가 호출되고 goroutine에서 실행되는 코드와 관련된 CPU 레지스터 관련 항목이 스케줄러가 수행 할 작업을 결정할 때 스택에 이미 있습니다.

그렇습니다. syscall이 완료되어 os 스레드가 차단 될 위험이있는 경우 syscall을 수행하는 goroutine은 자체 os 스레드를 얻습니다.이 스레드는 GOMAXPROCS에 포함되지 않습니다.

+0

차단 작업이 수행 될 때 CPU 레지스터는 어떻게됩니까? 현재 스레드가 goroutines에 의해 차단되고 있습니다. Go 스케줄러가 새 시스템 스레드를 만들고 다른 스레드를 모두 마이그레이션합니까? –

+0

나는이 질문에 대한 나의 대답에 당신의 의견에 대답했다. – Krom

1

일반적으로 goroutine이 런타임에 시스템 호출을 통해 작업을 요청할 때 이러한 상황에서 블로킹이 발생합니다. 예를 들어, 소켓에서 듣기 - goroutine은 데이터가 도착했을 때 시스템의 kqueue/epoll 부분에 깨어나게 해줍니다. 그 시점에서 매우 분명히 차단됩니다.

채널에서 메시지를 기다리는 중에도 골 루틴이 차단됩니다. 여기에서 goroutine은 메시지를 수신 할 때까지 다른 작업을 수행하지 않을 것이라고 명시 적으로 런타임에 말했습니다. 따라서 런타임은 골 루틴이 막힌.

"이 작업을 수행하고 결과를 제공하십시오"또는 "준비가되면이 사실을 알려주십시오"와 같은 대부분의 작업은 검증 가능한 작업을 차단하고 준비 될 때까지 잠자기 상태가됩니다.

관련 문제