golang--通过chan实现互斥锁

通过chan实现互斥锁

利用 select+chan 的方式,很容易实现 TryLock、Timeout 的功能

原理

chan中有一把锁lock 可以保护chan中的字段,同时chan的send和recev 两种角色存在一种hapends-befores的关系。

type hchan struct {
	qcount   uint           // total data in the queue
	dataqsiz uint           // size of the circular queue
	buf      unsafe.Pointer // points to an array of dataqsiz elements
	elemsize uint16
	closed   uint32
	elemtype *_type // element type
	sendx    uint   // send index
	recvx    uint   // receive index
	recvq    waitq  // list of recv waiters
	sendq    waitq  // list of send waiters

	// lock protects all fields in hchan, as well as several
	// fields in sudogs blocked on this channel.
	//
	// Do not change another G's status while holding this lock
	// (in particular, do not ready a G), as this can deadlock
	// with stack shrinking.
	lock mutex
}

第一种方法

第一种方法指的是chan的cap为1,放入一个元素代表获得锁,谁获得了这个元素则获取到锁。

type Mutex struct {
	ch chan struct{}
}

// init clock
func NewMutex() *Mutex {
	mutex := &Mutex{
		ch: make(chan struct{}, 1),
	}
	mutex.ch <- struct{}{}
	return mutex
}

// get lock
func (m *Mutex) Lock() {
	<-m.ch
}

// return lock
func (m *Mutex) Unlock() {
	select {
	case m.ch <- struct{}{}:
	default:
		panic("unlock the unlocked mutex")
	}
}

// try get lock
func (m *Mutex) TryLock() bool {
	select {
	case <-m.ch:
		return true
	default:
		return false
	}
}

func (m *Mutex) LockTimeout(timeout time.Duration) bool {
	timer := time.NewTimer(timeout)
	select {
	case <-timer.C:
	case <-m.ch:
		timer.Stop()
		return true
	}
	return false
}

func (m Mutex) IsLocked() bool {
	return len(m.ch) == 0
}

第二种方法

第二种法法指的是chan的cap为1,空槽为锁,能成功发送到chan的则获取到了锁。

type Mutex struct {
	ch chan struct{}
}

// init clock
func NewMutex() *Mutex {
	mutex := &Mutex{
		ch: make(chan struct{}, 1),
	}
	return mutex
}

// get lock
func (m *Mutex) Lock() {
	m.ch <- struct{}{}
}

// return lock
func (m *Mutex) Unlock() {
	select {
	case <-m.ch :
	default:
		panic("unlock the unlocked mutex")
	}
}

// try get lock
func (m *Mutex) TryLock() bool {
	select {
	case m.ch <- struct{}{}:
		return true
	default:
		return false
	}
}

func (m *Mutex) LockTimeout(timeout time.Duration) bool {
	timer := time.NewTimer(timeout)
	select {
	case <-timer.C:
	case m.ch <- struct{}{}:
		timer.Stop()
		return true
	}
	return false
}

func (m Mutex) IsLocked() bool {
	return len(m.ch) == 1
}

引用:go 并发编程实战课 — 鸟窝

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值