Golang:互斥锁已保持太长时间后出现恐慌

I am trying to figure out what is that is making my program hanging, most of my locks shouldn't be held for more than 200 ms. (actually much less!)

I want to create two new functions (Lock() and Unlock()) so that Lock will have a timer that will panic if Lock has been held for more than 200 ms.

This is my current attempt, but it doesn't work, any hint?

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()
}

Your lock function waits for 10 seconds befor calling the f function which holds the select statement, a simpler way of achieving what you are trying to do might be this:

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

You need to use the return value of time.AfterFunc. Here is a working example:

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!")
}

Playground link: https://play.golang.org/p/WVPp0_Iqlb

You have said you want your code to panic if the lock has been hold for 200 ms, but you gave the timer 10 seconds to wait. This will simply wait for 10 seconds before panicing instead of 200. I have tried your code editing it the following way :

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 works just fine and panics. If you drop the duration in the main function to 200 * time.Millisecond, it will not panic and just stop running.