2016-05-02 7 views
0

Ich versuche herauszufinden, was das ist, hängt mein Programm hängen, die meisten meiner Schlösser sollten nicht für mehr als 200 ms gehalten werden. (eigentlich viel weniger!)Golang: Panik nachdem Mutex Schlösser zu lange gehalten wurden

Ich möchte zwei neue Funktionen erstellen (Lock() und Unlock()), so dass Lock einen Timer hat, der in Panik gerät, wenn Lock für mehr als 200 ms gehalten wurde.

Dies ist mein aktueller Versuch, aber es funktioniert nicht, irgendein Hinweis?

type ShardKV struct { 
    lockChan chan bool 
} 

func (kv *App) lock(reason string) { 
    kv.mu.Lock() 

    f := func() { 
     fmt.Println("PANIC: ms passed") 
     select { 
     case <- kv.lockChan: 
      // 
     default: 
      panic("PANIC: " + reason) 
     } 
    } 
    time.AfterFunc(time.Second * 10, f) 
} 

func (kv *App) unlock(reason string) { 
    kv.lockChan <- true 
    kv.mu.Unlock() 
} 
+0

Wie erstellen Sie den Kanal? Es muss gepuffert werden, damit dieser Code funktioniert – creker

+0

Ihr Code wartet 10 Sekunden, aber Sie sagen, dass Sie für 200 ms beabsichtigen. Sie haben nicht angegeben, warum Ihr Code nicht funktioniert. Könnte das der Grund sein? –

Antwort

0

Ihre Lock-Funktion wartet 10 Sekunden vor dem die f-Funktion aufrufen, die die Select-Anweisung hält, eine einfachere Art und Weise zu erreichen, was Sie versuchen, dies zu tun wäre:

func (kv *App) lock(reason string) { 
    kv.mu.Lock() 
    select { 
    case <- kv.lockChan: 
     // 
    case <-time.After(time.Second * 10): 
     panic("PANIC: " + reason) 
    } 
} 
+0

Dies ist ein besserer Ansatz als der Code des OP versucht. Es ist einfacher zu verstehen * und * führt beide besser aus. – evanmcdonnal

+2

Ihr Code ist falsch. Die Sperrfunktion des OPs sperrt den Mutex, startet den Timer und kehrt zurück. Der Timer wartet im Hintergrund und überprüft nach 10 Sekunden, ob der Mutex entsperrt ist. Ihre Sperrfunktion wird für 10 Sekunden blockiert oder bis der Mutex entsperrt ist. Das ist nicht, was das OP will und Ihre Lösung ist schlimmer. Sie blocken 10 Sekunden lang nicht, Sie warten im Hintergrund. – creker

0

Sie müssen Verwenden Sie den Rückgabewert time.AfterFunc. Hier ist ein funktionierendes Beispiel:

package main 

import (
    "fmt" 
    "sync" 
    "time" 
) 

type Foo struct { 
    m sync.Mutex 
    timer *time.Timer 
} 

func (f *Foo) lock() { 
    f.m.Lock() 
    f.timer = time.AfterFunc(3 * time.Second, func() { 
     panic("Too long!") 
    }) 
} 

func (f *Foo) unlock() { 
    f.timer.Stop() 
    f.m.Unlock() 
} 

func main() { 
    foo := &Foo{ 
     sync.Mutex{}, 
     &time.Timer{}, 
    } 

    foo.lock() 

    // Uncomment this to see the difference 
    //time.Sleep(5 * time.Second) 

    foo.unlock() 
    fmt.Println("Success!") 
} 

Spielplatz Link: https://play.golang.org/p/WVPp0_Iqlb

+0

@nick Löscht das dein Problem? –

0

Sie haben gesagt, Sie Ihren Code wollen in Panik zu geraten, wenn die Sperre halten, für 200 ms ist, aber man gab den Timer 10 Sekunden zu warten. Dies wird einfach 10 Sekunden lang warten, bevor sie statt 200 panicing Ich habe den Code der Bearbeitung die folgende Art und Weise versucht:

package main 

import (
    "sync" 
    "fmt" 
    "time" 
) 


type App struct { 
    mu sync.Mutex 
    lockChan chan bool 
} 

func (kv *App) lock(reason string) { 
    kv.mu.Lock() 

    f := func() { 
     fmt.Println("PANIC: ms passed") 
     select { 
     case <- kv.lockChan: 
     // 
     default: 
      panic("PANIC: " + reason) 
     } 
    } 
    time.AfterFunc(time.Millisecond * 200, f) 
} 

func (kv *App) unlock(reason string) { 
    kv.lockChan <- true 
    kv.mu.Unlock() 
} 

func NewApp() *App { 
    app := App{} 
    app.lockChan = make(chan bool) 
    return &app 
} 

func main() { 
    app := NewApp() 
    app.lock("locking") 
    time.Sleep(time.Millisecond * 300) 

} 

Above Code funktioniert gut und gerät in Panik. Wenn Sie die Dauer in der Hauptfunktion auf 200 * time.Millisecond setzen, wird es nicht in Panik geraten und einfach aufhören zu laufen.