2017-10-06 4 views
-2

여러 번 병렬로 기능을 실행해야합니다.
함수가 true (채널에 true을 보내는 경우)을 반환하면 최종 결과는 true이되어야합니다.골란에 채널이 붙어 있습니다.

goroutines와 채널을 사용하여 어떻게 이것을 할 수 있습니까?

// Some performance intensive function 
func foo(i int, c chan bool) { 
    // do some processing and return either true or false 
    c <- true // or false 
} 

func main() { 
    flg := false 
    ch := make(chan bool) 
    for i := 0; i < 10; i++ { 
     go foo(i, ch) 
    } 
    // If even once foo() returned true then val should be true 
    flg = flg || <-ch 
} 
+0

"채널을 사용하여 어떻게이 작업을 수행합니까?" --- 채널을 사용해야하는 이유는 무엇입니까? – zerkms

+1

귀하의 시도를 보여주십시오. 코드에서 채널을 전혀 사용하지 않습니다. – Flimzy

+0

(코드는 쓰여진대로 읽기가 쉽지 않으므로'gofmt'도 사용하는 것이 좋습니다) – Flimzy

답변

0

합니다 (foo() 통화 중 하나가 보낸 값이 될 것이다 예측할 수없는 많은 어떤) ,하지만 당신은 모든 것을 받기를 원합니다. 귀하의 경우는 수신 한 true 값까지 루프에 충분하다하지만 그 뜻을 같이

for i := 0; i < 10; i++ { 
    flg = flg || <-ch 
} 

을 :

은 그래서 당신이 (전송) 보낼만큼의 값을받을 for 루프를 사용 flg의 최종 값을 결정할 수 있지만 나머지 값은 차단되도록 모든 값을 수신하는 것이 좋습니다 ( ch은 버퍼링되지 않은 채널 임). 이 예제에서는 중요하지 않지만 "실제"응용 프로그램에서는 goroutines가 영원히 멈추게됩니다 (메모리 누출).

당신이 완료 (즉시 하나 개 true 값이 발생으로) 가능한 한 빨리 복귀하기 위해 모든 foo() 호출을 기다리지 않으려면

는 옵션 때문에 모든 goroutines은에 값을 보낼 수 ch 버퍼링하는 것입니다 방해받지 않고.그리고 당신은 (대기 및 이에 따른)를 수신 할 필요가 없습니다 이런 식으로 모든 foo() 호출이 완료 :

ch := make(chan bool, 10) 
for i := 0; i < 10; i++ { 
    go foo(i, ch) 
} 

flg := false 
for i := 0; i < 10; i++ { 
    if <-ch { 
     flg = true 
     break 
    } 
} 

이 방법을 선택, 당신은 작업을 더 이상 불필요한 CPU를 피하기 위해 필요한 goroutines을 취소 할 수있는 수단을 제공해야한다 (및 메모리) 사용. context.Context은 그와 같은 의미이므로 자세한 내용은 Close multiple goroutine if an error occurs in one in go을 참조하십시오.

1

당신은 채널 ch에서 읽기 시작하고 진정한 결과를 일단 trueflg를 설정할 수 있습니다. 이처럼 :

//flg = flg || <- ch 
for res := range ch { 
    if res { 
     flg = true 
    } 
} 

이러한 방식으로 작동하지만 하나의 심각한 단점이있다 - for 루프는 무한 채널에서 새로운 값을 기다립니다. 관용적 인 방법은 채널을 닫는 것입니다. 이렇게 할 수 있습니다 : 모든 goroutines가 종료 될 때까지 기다릴 별도의 goroutine을 실행하십시오. Go는 매우 편리한 도구 인 sync.WaitGroup을 제공합니다.

글로벌 범위에서 정의 그래서 모든 goroutine은에 액세스 할 수 있습니다

for i := 0; i < 10; i++ { 
    wg.Add(1) // here 
    go foo(i, ch) 
} 

때 goroutine 마감 :

var (
    wg sync.WaitGroup 
) 

그런 다음 당신이 시작할 때마다 당신이 그룹을 기다리는 또 하나의 goroutine을 추가 goroutine 그것을 표시하는 방법은 wg.Done입니다.

func foo(i int, c chan bool) { 
    //do some processing and return either true or false 
    c <- true //or false 
    wg.Done() // here 
} 

그런 다음 seatate goroutine은 모든 foo goroutines가 채널을 종료하고 종료 할 때까지 대기합니다. 모든 때까지 wg.Wait 블록 완료 :

go func() { 
    wg.Wait() 
    close(ch) 
}() 

을 모두 함께 : 한 채널에서 하나 개의 값을받을 https://play.golang.org/p/8qiuA29-jv