2013-04-02 8 views
24

W tutorialu GO, mamy ten slajd:Dlaczego wymagany jest time.sleep do uruchomienia niektórych goroutines?

http://tour.golang.org/#62

package main 

import (
    "fmt" 
    "time" 
) 

func say(s string) { 
    for i := 0; i < 5; i++ { 
     time.Sleep(100 * time.Millisecond) 
     fmt.Println(s) 
    } 
} 

func main() { 
    go say("world") 
    say("hello") 
} 

Uruchomienie tego kodu produkuje Oczekiwane rezultaty ("świat" i "Hello" napisane na ekranie zamiennie 5 razy).

Jeśli jednak wykomentuj time.Sleep (a co za tym idzie, linia "time" importu) i uruchomić program ponownie, jesteśmy w lewo z tylko „Hello” napisane na ekranie pięć razy.

Co jest tak ważnego w przypadku time.Sleep, które oszczędza goryntynę przed śmiercią?

Odpowiedz

29

Jeśli usuniesz time.Sleep, nie dasz okazji do uruchomienia goroutine say("world"). Program planujący goroutine nie działa prewencyjnie. Twoje goryle muszą zrezygnować z kontroli, zanim uruchomi się kolejny goroutine. Jednym ze sposobów na rezygnację z kontroli jest uruchomienie time.Sleep.

Jeśli wyjąć time.Sleep z funkcji say następnie podstawowym goroutine przebiega 5 razy, nie rezygnując sterowanie do wtórnego goroutine i wtedy, gdy podstawowy powraca goroutine z say program wychodzi, bo nie ma nic, aby utrzymać program przy życiu .

7

Ponieważ program planujący goroutine nie działa prewencyjnie, twoje goryle muszą zrezygnować z kontroli, zanim uruchomi się kolejna goroutyna. Jednym ze sposobów rezygnacji z kontroli jest time.Sleep. Innym sposobem jest runtime.Gosched().

Oto poradnik zmodyfikowane do wykorzystania Gosched(): http://play.golang.org/p/jQ9mlGYXXE

Jest to przydatna lekcja w zrozumieniu goroutines. Jednak próba kontrolowania harmonogramu bezpośrednio jest zdecydowanie anty-wzorem; smutek często będzie następował.

Zamiast tego, pomyśl więcej o goroutinach, takich jak fragmenty komunikacji sprzętu cyfrowego (maszyny stanu są dobrą analogią). Lepiej dowiedzieć się o modelu Communicating Sequential Processes, na którym opierają się goryle. W projekcie opartym na CSP, każda goroutine ma swoje własne państwo prywatne i wymienia komunikaty, aby oddziaływać ze stanem innych goroutinów. Przekazywanie wiadomości wymusza synchronizację, której używa program planujący w celu określenia, które działanie pobiera czas procesora i co zostanie umieszczone w kolejce oczekiwania.

Gdy podchodzisz do tej metody, prawdopodobnie nigdy nie będziesz musiał martwić się o elementy wewnętrzne programu planującego.

+1

Rezultat, jaki uzyskuję z 'runtime.Gosched()' jest nieco inny. Otrzymuję 5: cześć i 4: świat. Podczas gdy z 'time.Sleep()' otrzymuję po 5 każdego. – Akavall

1

Jeśli usuniesz czas. Śpij z funkcji wypowiedzenia, a główny wykona wypowiedzieć ("cześć") i przerwie bez wykonywania goroutine. Jeśli dodasz czas. Spać (lub w inny sposób wybrać {}) przed głównym końcem da czas goroutine do uruchomienia i ten wątek zostanie wybrany z harmonogramu.

Przykład:

package main 

import (
    "fmt" 
    "time" 
) 

func say(s string) { 
    for i := 0; i < 5; i++ { 
     // time.Sleep(100 * time.Millisecond) 
     fmt.Println(s) 
    } 
} 

func main() { 
    go say("world") 
    say("hello") 

    time.Sleep(1*time.Second) 
    // Vs: 
    // select {} // blocks indefinitely, requires manual interrupt 
      // In CSP-speak the empty select is like STOP. 
      // for{} would cause the cpu to max and the process's STATE will be `running` 
      // select{} will not cause the cpu to max and the process state will be `sleeping` 
} 

Wyjście będzie zazwyczaj 5 cześć następnie 5 świata ale może również zarządzać, aby wydrukować jedną z świata przed ostatnim cześć

TRY IT -> (http: //) goo.gl/K2v7H0

Powiązane problemy