github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/18channeluse/trylock/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "sync" 6 "sync/atomic" 7 "unsafe" 8 ) 9 10 // https://colobu.com/2018/03/26/channel-patterns/ 11 12 // defined in sync.Mutex 13 const mutexLocked = 1 << iota 14 15 type Mutex struct { 16 mu sync.Mutex 17 } 18 19 func (m *Mutex) Lock() { 20 m.mu.Lock() 21 } 22 23 func (m *Mutex) Unlock() { 24 m.mu.Unlock() 25 } 26 27 func (m *Mutex) TryLock() bool { 28 // 之所以可以用 m.mu 结构体的指针 直接转成 int32 就是因为sync.Mutex 的首字段是int32类型 29 return atomic.CompareAndSwapInt32((*int32)(unsafe.Pointer(&m.mu)), 0, mutexLocked) 30 } 31 32 func (m *Mutex) IsLocked() bool { 33 return atomic.LoadInt32((*int32)(unsafe.Pointer(&m.mu))) == mutexLocked 34 } 35 36 func main() { 37 var m Mutex 38 if m.TryLock() { 39 fmt.Println("locked: ", m.IsLocked()) 40 m.Unlock() 41 } else { 42 fmt.Println("failed to lock") 43 } 44 }