golang mysql 非阻塞_golang非阻塞锁的简单实现

对于复杂类型如 container/list ,需要在所有读写操作上使用 sync.mutex 互斥锁以保证数据一致性,互斥锁并发情况下,Lock 操作会阻塞,一直等到其他线程Unlock,但是有的时候因为有一个耗时比较长的操作一直占用锁,我们想让其他线程不在Lock上一直阻塞,而是直接走其他业务流程。

举一个很简单的场景:在多人并发抽奖环节,为了保证不出现负库存,我们可以通过竞争锁,第一个获取锁的人可能中奖,而其他并发过来的请求获取锁失败(而不是一直阻塞在Lock()),直接当做未中奖处理。

思考了一下,有一个思路,我们可以用两道锁,第一道锁用来判断锁状态,第二道锁才是真正的耗时任务用的锁。

直接上代码

type NBLocker struct{

l1 sync.Mutex

l2 sync.Mutex

locked bool

}

func (NBLocker *NBLocker) Lock() (success bool) {

NBLocker.l1.Lock()

defer NBLocker.l1.Unlock()

if NBLocker.locked == false {

NBLocker.locked = true

success = true

NBLocker.l2.Lock()

}

return

}

func (NBLocker *NBLocker) Unlock() {

NBLocker.l1.Lock()

defer NBLocker.l1.Unlock()

NBLocker.locked = false

NBLocker.l2.Unlock()

}

使用

type foo struct {

mux NBLocker

}

func (self *foo) Bong(wg *sync.WaitGroup) {

defer wg.Done()

if !self.mux.Lock() {

fmt.Println("获取锁失败")

return

}

defer self.mux.Unlock()

time.Sleep(time.Second) //停顿一秒

fmt.Println("bong~")

}

func main() {

f := &foo{}

wg := &sync.WaitGroup{}

wg.Add(4)

go f.Bong(wg)

go f.Bong(wg)

go f.Bong(wg)

time.Sleep(time.Second *2)

go f.Bong(wg)

wg.Wait()

}

如果获取第二道锁失败,NBLocker.Lock() 方法会直接返回false,这时候只需要判断一下就可以直接跳过"抽奖环节"

以上例程输出

获取锁失败

获取锁失败

bong~

bong~

有疑问加站长微信联系(非本文作者)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值