2016-08-16 28 views
3

下面的代碼有時會輸出2。爲什麼不是所有的等候隊都等待完成?爲什麼WaitGroup有時不等所有的goroutines?

type Scratch struct { 
    //sync.RWMutex 
    Itch []int 
} 

func (s *Scratch) GoScratch(done chan bool, j int) error { 

    var ws sync.WaitGroup 

    if len(s.Itch) == 0 { 
      s.Rash = make([]int, 0) 
    } 
    for i := 0; i < j; i++ { 
      ws.Add(1) 
      go func (i int) { 
        defer ws.Done() 

        s.Rash = append(s.Rash, i) 
      }(i) 
    } 
    ws.Wait() 
    done<- true 
    return nil 
} 

func main() { 
    done := make(chan bool, 3) 
    s := &Scratch{} 
    err := s.GoScratch(done, 3) 
    if err != nil { 
      log.Println("Error:%v",err) 
    } 
    <-done 
    log.Println("Length: ", len(s.Rash)) 
}` 

奇怪的是我不能得到它輸出2與主要功能,但是當我使用測試用例有時它輸出2。

回答

5

代碼中存在競態條件。正是在這裏:

go func (i int) { 
    defer ws.Done() 
    // race condition on s.Rash access 
    s.Rash = append(s.Rash, i) 
}(i) 

由於所有的夠程訪問s.Rash同時,這可能會導致片的更新將被覆蓋。試着用sync.Mutex鎖定運行相同的代碼,以防止這一點:

// create a global mutex 
var mutex = &sync.Mutex{} 

// use mutex to prevent race condition 
go func (i int) { 
    defer ws.Done() 
    defer mutex.Unlock() // ensure that mutex unlocks 

    // Lock the resource before accessing it 
    mutex.Lock() 
    s.Rash = append(s.Rash, i) 
}(i) 

你可以閱讀更多關於這個herehere

+0

我不知道我錯過了什麼 - 應該休息一下。謝謝, – Sridhar

+0

有時候,你可以使用一個緩衝通道來替代使用一個片的互斥體。 https://play.golang.org/p/CGdz4T2Qn5 – Billy

3

如果你與種族探測器

go test -race . 

運行你的代碼,你會發現在片s.Rash競爭狀態。

相關問題