github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/18channeluse/trylock_timeout/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 ) 8 9 type Mutex struct { 10 ch chan struct{} 11 } 12 13 func NewMutex() *Mutex { 14 mu := &Mutex{make(chan struct{}, 1)} 15 mu.ch <- struct{}{} 16 return mu 17 } 18 19 func (m *Mutex) Lock() { 20 <-m.ch 21 } 22 23 func (m *Mutex) Unlock() { 24 select { 25 case m.ch <- struct{}{}: 26 default: 27 panic("unlock of unlocked mutex") 28 } 29 } 30 func (m *Mutex) TryLock(timeout time.Duration) bool { 31 timer := time.NewTimer(timeout) 32 select { 33 case <-m.ch: 34 timer.Stop() 35 return true 36 case <-time.After(timeout): 37 } 38 return false 39 } 40 41 // context的方式 42 func (m *Mutex) TryLock2(timeout time.Duration) bool { 43 ctx, cancel := context.WithTimeout(context.TODO(), timeout) 44 select { 45 case <-m.ch: 46 cancel() 47 return true 48 case <-ctx.Done(): 49 fmt.Println("err -> ", ctx.Err()) 50 } 51 return false 52 } 53 54 func (m *Mutex) IsLocked() bool { 55 return len(m.ch) == 0 56 } 57 func main() { 58 m := NewMutex() 59 ok := m.TryLock(time.Second) 60 fmt.Printf("locked v %v\n", ok) 61 ok = m.TryLock(time.Second) 62 fmt.Printf("locked %v\n", ok) 63 }