2014-02-18 8 views
5

Lassen Sie mich ein Beispiel verwenden:Kann ich die Beendigung einer Goroutine erzwingen, ohne darauf zu warten, dass sie zurückkehrt?

func WaitForStringOrTimeout() (string, error) { 
    my_channel := make(chan string) 
    go WaitForString(my_channel) 

    select { 
    case found_string := <-my_channel: 
    return found_string, nil 
    case <-time.After(15 * time.Minute): 
    return nil, errors.New("Timed out waiting for string") 
    } 
} 

In diesem einfachen Beispiel, ich habe eine Funktion WaitForString die Blöcke für eine Weile und schließlich einen String zurückgeben kann. Ich möchte WaitForString mit diesem Code umbrechen, der entweder die gleiche Zeichenfolge zurückgibt oder ein Zeitlimit mit einem Fehler anzeigt.

Wenn eine Zeichenfolge schnell gefunden wird, ist es noch ein goroutine mit einer irgendwo schlafen Anweisung 15 Minuten laufen oder dieser Müll irgendwie gesammelt?

Wenn die Zeitüberschreitung auftritt und eine Zeichenfolge nie gefunden wird, gibt es noch eine goroutine, die WaitForString ausführt, obwohl es keine anderen Routinen gibt, die ihre Ausgabe beobachten können? Was passiert, wenn WaitForString viel Speicher zuweist, aber nie zurückkehrt?

Gibt es irgendeine Weise, die ich WaitForString machen kann() Kenntnis von der Timeout auftritt und aufgeben?

+1

Ja, es wird halten, selbst wenn der Ausgangskanal läuft geschlossen ist. Die Timeout-Erkennung sollte in 'WaitForString' leben. Ich glaube nicht, dass es eine Möglichkeit gibt, die Goroutine zu bereinigen, indem man sie einpackt. – Alex

+0

Sicher, ich könnte WaitForString() ändern, aber das ist ein einfaches Beispiel. Was ist, wenn der 2. Fall kein Timeout ist, sondern WaitForOtherString(). Ich muss nur warten, bis einer von ihnen fertig ist. Dann stecke ich wieder fest, da ich noch eine Funktion "über" diesen beiden mit der Select-Anweisung brauche. Wie kann ich die langsamere Goroutine stoppen? – Gregable

+1

Letztendlich müssen Sie die Unterbrechungen selbst verwalten. Sehen Sie sich zum Beispiel http://play.golang.org/p/bpOGkIN9Ng an. WaitForString() muss beachten, dass es möglicherweise unterbrochen wird, und es muss einen Mechanismus geben, um es zu unterbrechen. Vielleicht kannst du auch panic/recover benutzen. – Alex

Antwort

2

Im Allgemeinen keine gibt es keine Möglichkeit, eine andere goroutine zu stoppen. Es gibt eine runtime.Goexit Funktion, die verwendet werden kann, um das Beenden der aktuellen Goroutine zu veranlassen (selbst wenn sie von einem tiefen Aufrufrahmen aufgerufen wird), aber nichts, um zu bewirken, dass andere Goroutinen beendet werden. Für den spezifischen Fall des Moduls time gibt es keine separate Goroutine, die jeden Timer oder Ticker behandelt: stattdessen werden Timer zentral von der Laufzeit verwaltet, so dass sie erkennen kann, wann sie als nächstes aufwachen muss.

Während keine goroutine gibt es rumhängen, der Kanal und eine kleine Buchhaltung Struktur wird für die 15 Minuten bleiben, um.

Wenn dies ein Problem ist, verwenden Sie time.NewTimer anstelle von time.After, und stoppen Sie den Timer manuell, wenn Sie zurückkehren. Zum Beispiel:

t := time.NewTimer(15 * time.Minute) 
defer t.Stop() 
select { 
case found_string := <-my_channel: 
    return found_string, nil 
case <-t.C: 
    return nil, errors.New("Timed out waiting for string") 
} 

time.After ist wirklich nützlich für die genaue periodisches Verhalten, während time.NewTimer für einfache Timeouts gut funktioniert.

+0

Related, Bedeutet das, dass ich das Zeitmodul etwas ist, das ich nicht umsetzen konnte? IE: Ist es mir möglich, eine Goroutine zu schreiben, die genau wie der Timer arbeitet und von etwas außerhalb des Codes geweckt wird? – Gregable

+0

Sie könnten wahrscheinlich etwas ähnliches mit 'syscall implementieren.Select ': Der Punkt ist, dass wenn zwei Timer auf 1 Sekunde bzw. 2 Sekunden ablaufen, brauchen Sie nicht zwei goroutines, um sie zu wecken: stattdessen können Sie eine Goroutine haben, die 1 Sekunde wartet und dann die erste aufweckt Timer und wartet dann eine weitere Sekunde, um den zweiten zu wecken. Die Verwaltung dieser Art von Datenstruktur kann etwas komplexer sein, ist aber machbar. –