2014-01-08 2 views
1

내가 벤치 마크 이동 채널 처리량에 작은 프로그램을 만든 교착 상태, 그러나 그것은 항상 교착 상태, 나는 매우 열심히 노력하지만 이해할 수없는 이유 : 당신의 노동자가 하나 개의 작업을 처리테스트는 채널 처리량을 이동 - 모든 goroutines이

package main 

import (
    "fmt" 
    "runtime" 
) 

const CONCURRENCY = 32 
const WORK_PER_WORKER = 100 
const TOTAL_WORK = CONCURRENCY * WORK_PER_WORKER 

func work() { 
    sum := 0 
    for i := 0; i < 10000000; i++ { 
     sum *= i 
    } 
} 

type WorkItem struct { 
    Done chan int 
} 

func main() { 
    runtime.GOMAXPROCS(CONCURRENCY) 
    var workQueue [CONCURRENCY]chan *WorkItem 
    // initialize workers 
    for i := 0; i < CONCURRENCY; i++ { 
     workQueue[i] = make(chan *WorkItem) 
    } 
    // start workers 
    for i := 0; i < CONCURRENCY; i++ { 
     go func(i int) { 
      anItem := <-workQueue[i] 
      work() 
      anItem.Done <- 1 
     }(i) 
    } 
    completed := make(chan bool, TOTAL_WORK) 
    for i := 0; i < TOTAL_WORK; i++ { 
     go func(i int) { 
      // send work to queues 
      workToDo := &WorkItem{Done: make(chan int)} 
      workQueue[i/WORK_PER_WORKER] <- workToDo // !! DEADLOCK 
      // wait until the work is done 
      <-workToDo.Done 
      completed <- true 
     }(i) 
    } 
    fmt.Println("Waiting") 
    for i := 0; i < TOTAL_WORK; i++ { 
     <-completed 
    } 
} 

답변

2

귀하의 코드 go func(i int) { anItem := <-workQueue[i]; ... }workQueue[i]에서 juste 1 개 항목을 제거하지만 당신이 그것으로 WORK_PER_WORKER 항목을 물건하려고합니다. 당신은 많은 항목을 동시로 처리 할 것이고 그 후에 모든 독서 goroutine은 종료되고 교착 상태에 빠지게됩니다.

작업자 루핑으로 인해 goroutines는 교착 상태를 "해결"합니다. http://play.golang.org/p/j2pavqnBDv 이러한 작업자 goroutines는 절대로 종료되지 않으므로 "해결"됩니다. 어쩌면 당신은 아무 것도 보내지 않을 때 당신의 채널을 close으로 실험하여 작업자에게 알려줄 수 있습니다.

1

때문에 그런 다음 종료하십시오. 따라서 처음에는 CONCURRENCY 항목 만 진행되고 workQueue[i/WORK_PER_WORKER] <- workToDo 블록은 무의식적으로 진행됩니다. 따라서 completed chan은 충분한 값을받지 못하고 main도 영원히 차단됩니다.

담당 직원은 다음과 같이 루프에서 작업을 수행해야합니다

for i := 0; i < CONCURRENCY; i++ { 
    go func(i int) { 
     for anItem := range workQueue[i] { 
      work() 
      anItem.Done <- 1 
     } 
    }(i) 
} 
관련 문제