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  }