Чтобы добавить немного к ответ Адриана : мы не знаем, в каком порядке могли бы выполняться эти две программы. Если ваш сон наступает раньше, чем отправка по каналу, и он спит «достаточно долго», 1 , что гарантирует, что программа other сможет выполнить свою отправку. Если обе программы выполняются «одновременно» и не ждут (как в исходном примере Тура), мы не можем быть уверены, какая из них действительно достигнет своей строки c <- sum
первой.
Запуск примера Тура на Go Игровая площадка (либо напрямую, либо через веб-сайт Тура), я на самом деле получаю:
-5 17 12
в окне вывода, которое (потому что мы знаем, что -9
находится во 2-й половине slice) говорит нам, что секунда goroutine «добралась» (до канала-send) первой. В некотором смысле это просто удача, но при использовании Go Playground все задания выполняются в довольно детерминированной среде c, с одним ЦП и с совместным планированием, так что результаты более предсказуемы. Другими словами, если вторая горутина попала туда первой за один проход, то, вероятно, будет на следующей. Если игровая площадка использует несколько процессоров и / или менее детерминированную среду c, результаты могут меняться от одного прогона к следующему, но это не гарантируется.
В любом случае, при условии, что ваш код делает то, что вы говорите (и я верю, что так и есть), это:
go sumSleep(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
заставляет первого отправителя ждать, а второй отправитель запускается первым. Но это то, что мы уже наблюдали, на самом деле произошло, когда мы позволили двум рутинным гонкам. Чтобы увидеть изменение , нам нужно сделать секунду задержку отправителя.
Я сделал модифицированную версию примера в Go Playground здесь , который печатает больше аннотаций. С задержкой, вставленной во вторую половинную сумму, мы видим первую половинную сумму как x
:
2nd half: sleeping for 1s
1st half: sleeping for 0s
1st half: sending 17
2nd half: sending -5
17 -5 12
, как мы можем ожидать, поскольку одна секунда "достаточно длинна".
1 Как долго является"достаточно длинным"? Ну, это зависит от того, насколько быстры наши компьютеры? Сколько еще вещей они делают? Если компьютер достаточно быстрый, может потребоваться задержка в несколько миллисекунд или даже несколько наносекунд. Если наш компьютер действительно старый или очень занят другими задачами с более высоким приоритетом, то нескольких миллисекунд может не хватить времени. Если проблема достаточно большая, одной секунды может не хватить. Часто неразумно выбирать какое-то конкретное количество time , если вы можете лучше контролировать это с помощью какой-то операции synchronization , и обычно вы можете это сделать. Например, использование переменной sync.WaitGroup
позволяет подождать, пока n goroutines (для некоторого значения времени выполнения n) вызовет функцию Done
, прежде чем ваша собственная процедура будет выполнена.
Код игровой площадки, скопированный в StackOverflow для удобства
package main
import (
"fmt"
"time"
)
func sum(s []int, c chan int, printme string, delay time.Duration) {
sum := 0
for _, v := range s {
sum += v
}
fmt.Printf("%s: sleeping for %v\n", printme, delay)
time.Sleep(delay)
fmt.Printf("%s: sending %d\n", printme, sum)
c <- sum
}
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c, "1st half", 0*time.Second)
go sum(s[len(s)/2:], c, "2nd half", 1*time.Second)
x, y := <-c, <-c
fmt.Println(x, y, x+y)
}