2017-01-19 4 views
2

특정 조건이 나올 때까지 기다리는 중입니다. 최선의 방법에 대한 조언이 필요합니다. 나는 view 변수로 읽어 파일을 업데이트하고하는 goroutine에서채널 또는 sync.Cond를 사용하여 조건 대기

type view struct { 
    timeFrameReached bool 
    Rows []*sitRow 
} 

:이 (간체)과 같은 구조체가있다. 행 수가 증가하고 궁극적으로 timeFrameReachedtrue이됩니다.

다른 곳에서, 나는 사실로 다음과 같은 조건을 대기 할 :

view.timeFrameReached == true || len(view.Rows) >= numRows 

내가 채널을 배우려고 노력하고 있고 이동의 상태 변수가 어떻게 작동하는지, 나는 최선의 해결책이 여기에 무엇인지 알고 싶습니다 . 이론적으로 나는 다음과 같이 사소한 것을 할 수 있습니다.

그러나 이것은 분명히 순진한 해결책입니다. numRows의 값은 HTTP 요청에서 나왔으므로 조건 메서드가 어려워 보입니다. goroutine은 찾고있는 행의 수를 알지 못하기 때문에 조건을 브로드 캐스트 할시기를 알 수 없습니다.

답변

3

나는 이것을 조건 변수로 처리 할 것이라고 생각한다. 웨이터가 확인하고 싶은 조건이 참이지만 (즉, 확인 된 사항이 변경된 경우에만) Signal을 수행해야한다는 개념은 아닙니다.

이 작업을 수행하는 일반적인 패턴은 다음과 같습니다 그런

mutex.Lock() 
for { 
    view = getView() 
    if view.timeFrameReached == true || len(view.Rows) >= numRows { 
     break 
    } 
    cond.Wait(&mutex) 
} 
// Do stuff with view 
mutex.Unlock() 

, 코드에서 view이 변경되는 경우 : 분명히

mutex.Lock() 
// Change view 
cond.Signal() // or cond.Broadcast() 
mutex.Unlock() 

, 당신의 프로그램이 어떻게 작동하는지 모르고을 작성했습니다, 그래서 당신은 약간의 변경을해야 할 수도 있습니다.

신호를 보낼 채널을 보내고 대기중인 채널로부터 수신을 시도하면 채널과 비슷한 것을 할 수 있지만 그게 더 복잡해 보입니다. (만약 당신이 기다리고있는 하나 이상의 goroutine을 가지고 있다면, 모두 cond.Broadcast을 사용하여 깨우도록 신호 할 수 있습니다.)

+0

좋습니다. 나는 또한 내가 생각해 낸 대안 아이디어를 게시했다. – Josephus

+0

이것이 가능한 해결책이지만, 뮤텍스를 사용하면 결과적으로 확장 할 수 없다는 경험이 있습니다. 캡슐화하기 어려운 상세한 글로벌 지식이 필요할 수 있습니다. goroutines와 채널은 복합 요소를 형성합니다 (이것은 CSP의 핵심 기능입니다). 이와 같은 경우에는 대신이를 사용하려고합니다. –

1

하나의 아이디어는 채널을 통해 필요한 수의 행을 전달하는 것과 건물을 짓는 goroutine 뷰는 비 블로킹 수신을 수행하여 주 스레드가 특정 수의 행을 요청하는지 확인합니다. 그렇다면 조건을 충족했다는 메시지를 다시 보냅니다. 여기 goroutine 검사

if numRows > len(viewFile.View.Rows) && !viewFile.View.TimeFrameReached { 
    // Send the required number of rows 
    rows <- numRows 
    // Wait for the prefetch loop to signal that the view file is ready 
    <-rows // Discard the response value and move on 
    view = getView() 
} 

행의 특정 숫자가 요구되는 경우 :

여기에 main 함수는 행 번호를 요청한다. 그렇다면 준비가되면 긍정 신호로 응답합니다. 그 신호의 가치는 중요하지 않습니다.

select { 
    case numRows := <-rows: 
     if len(viewFile.View.Rows) >= numRows || viewFile.View.TimeFrameReached { 
      rows <- 1 
     } 
    default: 
} 
+0

이렇게하려면 두 개의 다른 채널이 필요합니다. 그렇지 않으면 어떤 코드가'numRows'를 읽는지 알 수 없습니다. –

+0

goroutine 내에서 동일한 채널의 양쪽 끝을 사용할 때주의하십시오. 버퍼되지 않은 채널은 일반적으로이 경우 교착 상태가됩니다. 위의 첫 번째 코드 단편은 위의 Andy의 의견에 동의합니다. –

+0

하나의 채널을 두 번 (위에서와 같이) 사용하는 것이지만 두 번째 인스턴스에서 보내기 방향을 변경하는 것입니다. 버퍼링되지 않은 채널이라면 어느 쪽이든 동기화 할 수 있습니다. –