扩展golang的sync mutex的trylock及islocked

前言:

      golang sync mutex本身是很好好用,但我的业务逻辑里面需要 非阻塞模式的拿锁 及 非阻塞得知锁的状态。那么说这么复杂,简单说是什么个意思? trylock, 我可以用非阻塞的模型进行拿锁,要么拿到锁,要么锁被别人拿到。 islocked, 就是判断锁的状态。

该文章后续仍在不断更新中, 请移步到原文地址 http://xiaorui.cc/?p=5084

实现的逻辑相对简单,就是使用golang atomic标准库做compareAndSet原子更新,  如果更新成功为拿到锁,否则,反之。  cas 底层是依赖cpu的指令集的,cas的操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。 如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值 。否则,处理器不做任何操作。

代码扔到github了,有兴趣的可以去看看,https://github.com/rfyiamcool/trylock

# xiaorui.cc

package trylock

import (
	"sync"
	"sync/atomic"
	"unsafe"
)

const (
	LockedFlag   int32 = 1
	UnlockedFlag int32 = 0
)

type Mutex struct {
	in     sync.Mutex
	status *int32
}

func NewMutex() *Mutex {
	status := UnlockedFlag
	return &Mutex{
		status: &status,
	}
}

func (m *Mutex) Lock() {
	m.in.Lock()
}

func (m *Mutex) Unlock() {
	m.in.Unlock()
	atomic.AddInt32(m.status, UnlockedFlag)
}

func (m *Mutex) TryLock() bool {
	if atomic.CompareAndSwapInt32((*int32)(unsafe.Pointer(&m.in)), UnlockedFlag, LockedFlag) {
		atomic.AddInt32(m.status, LockedFlag)
		return true
	}
	return false
}

func (m *Mutex) IsLocked() bool {
	if atomic.LoadInt32(m.status) == LockedFlag {
		return true
	}
	return false
}

总结:

      golang 的锁在功能上相比其他语言要弱一些,比如 golang是没有可重入锁的,官方人员说 Reentrant Lock 本身就不是一个好主意….  golang cond没有超时等待,所以很多时候你要一直等待下去。 但golang有自己的优点,golang sync mutex性能很高,因为他底层也是cas + go runtime 调度实现的。 后面我会分享下 sync mutex的源码实现。

END.


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc