2016-08-08 2 views
0

병렬 goroutines를 사용하여 복잡한 프로그램을 작성하려고합니다. 그것은 채널이있는 첫 번째 프로그램입니다;) 각 goroutine은 배열을 반환하지만 불행히도 결과는 "임의"입니다. 10 시간 동안 프로그램을 실행하면 10 가지 결과가 나옵니다. (배열 채널을 공유하는 골 루터 : 데이터 경주 해결 시도

이것은 내 프로그램이 지나치게 단순하므로 결과가 좋습니다 (너무 간단하기 때문에).하지만 -race 인수를 사용하여 실행하면, 4 개 데이터 종족이있다.

내가 가까운() 함수를 가지고 시도했지만이 일을하지 않았다.

당신이 날은 실수를 찾기 위해 도와 드릴까요? 대단히 사전에 감사합니다!

package main 

import "fmt" 
import "sync" 
import "strconv" 


func cat_strings(a int, b string) []string{ 
    var y []string 

    j := strconv.Itoa(a) 
    y = append(y, j) 
    y = append(y, b) 
    return y 
} 

func main() { 
    var slice []string 
    var wg sync.WaitGroup 
    var x []string 

    queue := make(chan []string, 10) 

    wg.Add(10) 
    for i := 0; i < 10; i++ { 
     go func(i int) { 
      defer wg.Done() 
      x = cat_strings(i, "var") 
      queue <- x 
     }(i) 

    } 
    //close(queue) 

    go func() { 
     defer wg.Done() 
     for t := range queue { 
      slice = append(slice, t...) 
     } 
    }() 

    wg.Wait() 
    fmt.Println(slice) 
} 
+0

채널에 정의되지 않은 순서로 10 가지를 넣으므로 여기에서 무슨 일이 일어날 지 확신하지 못합니까? – ams

답변

7

이 수정 프로그램에는 두 가지가 있습니다. goroutines간에 슬라이스를 공유하지 마십시오. 범위가 에 동기식으로 queue 이상인 경우

import (
    "fmt" 
    "strconv" 
    "sync" 
) 

func cat_strings(a int, b string) []string { 
    var y []string 

    j := strconv.Itoa(a) 
    y = append(y, j) 
    y = append(y, b) 
    return y 
} 

func main() { 
    var slice []string 
    var wg sync.WaitGroup 

    queue := make(chan []string, 10) 

    wg.Add(10) 
    for i := 0; i < 10; i++ { 
     go func(i int) { 
      defer wg.Done() 
      queue <- cat_strings(i, "var") 
     }(i) 

    } 

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

    for t := range queue { 
     slice = append(slice, t...) 
    } 

    fmt.Println(slice) 
} 

goroutines간에 공유 할 여분의 x 슬라이스의 이유는 없습니다. 각 goroutine에 다른 슬라이스가 필요한 경우 각각에 대해 새 슬라이스를 정의하십시오. 단일 슬라이스를 공유하면 항상 여분의 동기화가 필요합니다.

다른 레이스는 queue에서 slice 슬라이스까지 덧붙인 고 루틴과 최종 fmt.Println 사이에 있습니다. 모든 값을 읽을 때까지 인쇄하고 싶지 않으므로 동시 인쇄 할 이유가 없으므로 최종 값을 인쇄하기 전에 범위 내 루프를 완료하십시오.