Тупик при использовании канала с select - PullRequest
0 голосов
/ 03 декабря 2018

Я пытался переписать работающую программу, которая не использовала select или WaitGroup, чтобы она реализовала select и WaitGroup, но я столкнулся с проблемой, которую я могуне найти решение.Кажется, что возникла тупиковая ситуация, потому что функция Manager не получает данные из канала записи, поэтому канал заблокирован от отправки / получения, и программа блокируется.

Исходная рабочая Managerфункция, без select:

func Manager(list *[]Request, writerChan <-chan int) {
    ageIn, writersOpen := <-writerChan
    for {
        if writersOpen { // if writers channel is open

            Add(list, Request{Value: ageIn, Count: 1}) // putting new object to list
            ageIn, writersOpen = <-writerChan          // receiving new player from writer channe;

        } else {
            break
        }
    }
}

Итак, у меня была рабочая программа, но нужно было реализовать WaitGroup и select, есть обновленные коды:

Обновленная функция Manager с реализацией select:

func Manager(list *[]Request, writerChan <-chan int) {
    defer waitGroup.Done()
    for {
        select {
        case ageIn := <-writerChan:
            Add(list, Request{Value: ageIn, Count: 1}) // add player to list
        default:
            break
        }
    }
}

Обновленная функция Main с реализацией WaitGroup:

var waitGroup sync.WaitGroup

func main() {
    list := ParallelList{List: make([]Request, 0)}
    readers, teams, players := ReadData("data.txt")
    writerChan := make(chan int)          //any2one writers channel
    writerFinishChan := make(chan int, 6) // channel to know when all writers are done writing

    waitGroup.Add(6)

    for i := 0; i < len(teams); i++ {
        go Writer(teams, teams[i], writerChan, writerFinishChan)
    }

    go Manager(&list.List, writerChan)
    waitGroup.Wait()
}

Функция Writer, которая отправляет данные на writerChan

func Writer(teams [][]Player, team []Player, writerChan chan<- int,
    writerFinishChan chan int) {
    defer waitGroup.Done()
    count := len(team)
    for i := 0; i < count; i++ {
        writerChan <- team[i].Age
    }
    writerFinishChan <- 1 // when writer finishes writing, he puts 1 to the "writerFinishChan"

    if len(writerFinishChan) == len(teams) { // if all writers are done writing (the len should be equal to 6)
        close(writerChan)
    }
}

Итак, проблема в том, что после реализации select и WaitGroup моя программа небольше не работает должным образом, это дает мне «фатальную ошибку: горутины спят, тупик».

Может, кто-нибудь поможет мне разобраться с этой проблемой?Я совершенно уверен, что проблема заключается в функции Manager, и это select block

1 Ответ

0 голосов
/ 03 декабря 2018

Похоже, ваша логика для выхода из функции Manager теперь другая.Раньше вы ждали закрытия канала, однако теперь вы вообще не проверяете.На самом деле Manager никогда не выйдет.Это также подразумевает, что WaitGroup никогда не будет выполнено.

Я думаю, что выбор в Manager не нужен.Если вы закрываете канал, просто установите диапазон:

for ageIn := range writerChan {
  Add(list, Request{Value: ageIn, Count: 1}) // putting new object to list
}

Это будет правильно завершено, когда writerChan будет закрыт.

...