2016-11-03 3 views
2

간단한 작업자 풀을 구현하고 문제를 계속 실행하려고합니다. 내가하고 싶은 일은 더 많은 일을하기 전에 일정량의 일을하는 정해진 수의 근로자를 확보하는 것뿐입니다. 내가 비슷합니다 사용하고 코드 :Go의 간단한 작업자 풀

jobs := make(chan imageMessage, 1) 
    results := make(chan imageMessage, 1) 

    for w := 0; w < 2; w++ { 
     go worker(jobs, results) 
    } 

    for j := 0; j < len(images); j++ { 
     jobs <- imageMessage{path: paths[j], img: images[j]} 
    } 
    close(jobs) 

    for r := 0; r < len(images); r++ { 
     <-results 
    } 
} 

func worker(jobs <-chan imageMessage, results chan<- imageMessage) { 
    for j := range jobs { 
     processImage(j.path, j.img) 
     results <- j 
    } 
} 

나의 이해는이 한 번에 1 "일을"할 수있는이 명 노동자를 만들어야합니다 때까지 그들이 그 1 일을 완료로 더 많은 작업을 얻을 것이다가 그 외에 할일이 없다. 그러나 얻을 수 fatal error: all goroutines are asleep - deadlock!

내가 거대한 100 뭔가 버퍼를 설정하면이 작동하지만 한 번에 한 작업을 제한 할 수 싶어요.

나는 가깝지만 분명히 뭔가를 놓친 것처럼 느낍니다.

+0

관련에 비슷한 구현을 체크 아웃 : [이 이동에 관용적 작업자 스레드 풀인가?] (http://stackoverflow.com/questions/38170852/is-this-an-idiomatic- worker-thread-pool-in-go) – icza

답변

2

jobs 채널의 모든 작업을 성공적으로 보낸 후에 만 ​​results 채널의 "드레인"을 시작하는 것이 문제입니다. 그러나 모든 작업을 보낼 수 있으려면 jobs 채널에 충분한 버퍼가 있어야하거나 작업자 goroutine이 작업을 소비 할 수 있어야합니다.

하지만 작업자가 작업을 소비 할 때 다음 작업을 수행하기 전에 작업자는 results 채널에 결과를 보냅니다. results 채널의 버퍼가 가득 차면 결과를 보내지 않습니다.

하지만 마지막 부분 (결과를 보내는 데 차단 된 작업자 goroutine)은 results 채널에서 수신하여 "차단 해제"할 수 있습니다. 모든 작업을 전송할 수있을 때까지는 차단하지 않습니다. jobs 채널의 버퍼와 results 채널의 버퍼가 모든 작업을 수행 할 수 없으면 교착 상태가됩니다. 또한 버퍼 크기를 큰 값으로 늘리면 왜 작동하는지 설명합니다. 작업이 버퍼에 맞을 수 있고 교착 상태가 발생하지 않으며 모든 작업이 성공적으로 전송 된 후 최종 루프는 results 채널을 소모합니다.

해결책? 자체 goroutine에서 생성 및 송신 작업을 실행하므로 모든 작업을 보내기 위해 기다리지 않고 "즉시"results 채널로부터 수신을 시작할 수 있습니다. 즉, 작업자 goroutines가 영원히 결과를 보내려고 차단되지 않습니다. 즉

go func() { 
    for j := 0; j < len(images); j++ { 
     jobs <- imageMessage{path: paths[j], img: images[j]} 
    } 
    close(jobs) 
}() 

Go Playground에서 사용해보십시오.

또한 Is this an idiomatic worker thread pool in Go?

+0

정말 고마워요. 나는 내가 가까웠다는 것을 알았다 : P – FryDay