2016-04-11 4 views
0

Я пытаюсь использовать рабочие goroutines для проверки диаметров на определенном расстоянии, он отлично работает, когда я делаю одну плитку за раз, но когда я делаю связку, есть массовое замедление. Я полагаю, что это связано с тем, что многие горуты все еще работают, хотя они больше не нужны. Я добавил канал сбоя, чтобы сообщить всем работающим goroutines закрыть магазин, но при этом приложение зависает. Фактически, передача любого значения в канал заставляет приложение зависать, даже если я его не потребляю.Передача любого значения по каналу отмены приводит к зависанию программы

caught := 0 
loop: 
    for angle := float64(0); angle < 360; angle++ { 
     select { 
     case <-failChannel: 
      break loop 
     default: 
     log.Print(angle) 
     } 

    } 
    channelOut <- []int{radius, caught} 

является подпрограмма, которая использует канал

for { 
     select { 
     case circle := <-channelOut: 
      if circle[1] == 0 { 
       radiusMap[circle[0]] = 0 
       if _, radius := testLine(radiusMap); radius <= circle[0] { 
        failChannel <- 0 


       } 
      } else { 
       radiusMap[circle[0]] = 1 

      } 

     default:  
     } 
    } 

ли цикл, который будет проходить Int к failChannel. Я делаю int-канал, потому что хочу посмотреть, не сменился ли нижний радиус, и, если так, остановитесь. Я сделал это как раз в любом int сейчас, как тест.

Кто-нибудь знает, почему это будет висит? Мне кажется, это не имеет смысла.

+1

Пожалуйста, уменьшите свой код до минимума и предоставите полный рабочий образец (включая вызовы процедур). Весь материал окружности/радиуса не связан с каналами. –

+1

Имейте в виду, что если у вас есть более одного горута, которые рассчитывают на этот failchannel, у вас будет проблема. Только один из этих приемников каналов получит уведомление о сбое, но не все. –

+2

как вы инициализируете канал отказа? буферизуется? небуферизованный канал приведет к зависанию. – nevets

ответ

2

Вы можете закрыть канал для сигнала завершения:

failed := make(chan struct{}) 
select { 
case <-failed: 
} 

В другом goroutine:

close(failed) 

заставит failed случай произойдет. Это будет работать с любым количеством goroutines, прослушивающим failed. Будьте осторожны, чтобы сделать это только один раз, потому что закрытие уже закрытого канала будет паниковать. Вы можете использовать этот шаблон:

// A Stopper signals completion over C by closing it when Stop is called 
type Stopper struct { 
    C chan struct{} 
    once sync.Once 
} 

// NewStopper creates a new Stopper 
func NewStopper() *Stopper { 
    return &Stopper{ 
     C: make(chan struct{}), 
    } 
} 

// Stop closes C. It is safe to call multiple times 
func (s *Stopper) Stop() { 
    s.once.Do(func() { 
     close(s.C) 
    }) 
} 
Смежные вопросы