2016-07-12 4 views
4

복잡한 프로그램의 채널에서 불확실한 번호 작업을 실행 한 결과를 읽을 때 감지되지 않은 교착 상태가 발생하는 상황을 어떻게 처리합니까? 웹 서버?채널에서 읽는 동안 감지되지 않는 "교착 상태"

package main 

import (
    "fmt" 
    "math/rand" 
    "time" 
) 

func main() { 
    rand.Seed(time.Now().UTC().UnixNano()) 

    results := make(chan int, 100) 

    // we can't know how many tasks there will be 
    for i := 0; i < rand.Intn(1<<8)+1<<8; i++ { 
     go func(i int) { 
      time.Sleep(time.Second) 
      results <- i 
     }(i) 
    } 

    // can't close channel here 
    // because it is still written in 
    //close(results) 

    // something else is going on other threads (think web server) 
    // therefore a deadlock won't be detected 
    go func() { 
     for { 
      time.Sleep(time.Second) 
     } 
    }() 

    for j := range results { 
     fmt.Println(j) 
     // we just stuck in here 
    } 
} 

간단한 프로그램의 경우 detects a deadlock and properly fails이됩니다. 대부분의 예제는 알려진 수의 결과를 가져 오거나 채널에 순차적으로 씁니다.

+0

이것은 실제로 교착 상태가 아니다 - 당신은 자원을 경쟁하는 두 개의 스레드가없는, 당신은 결코 올 않을 데이터를 기다리고 하나 개의 스레드가 있습니다. 잠금이 필요 없습니다. – Adrian

+0

go 오류 메시지에서 매우 유사한 상황이 교착 상태를 요구합니다.'throw : 모든 goroutines이 잠들고 있습니다! '; 그러나 나는 당신의 요지를 본다. – sanmai

답변

7

트릭은 sync.WaitGroup을 사용하고 비 차단 방식으로 작업이 완료 될 때까지 기다리는 것입니다.

var wg sync.WaitGroup 

// we can't know how many tasks there will be 
for i := 0; i < rand.Intn(1<<8)+1<<8; i++ { 
    wg.Add(1) 
    go func(i int) { 
     time.Sleep(time.Second) 
     results <- i 
     wg.Done() 
    }(i) 
} 

// wait for all tasks to finish in other thread 
go func() { 
    wg.Wait() 
    close(results) 
}() 

// execution continues here so you can print results 

은 참조 : Go Concurrency Patterns: Pipelines and cancellation - The Go Blog