Skip to content

Commit

Permalink
feat(互斥锁[mutex]): 互斥锁 支持
Browse files Browse the repository at this point in the history
  • Loading branch information
Ccheers committed May 20, 2022
1 parent 6c3b36a commit 47367cd
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
77 changes: 77 additions & 0 deletions sync/try_lock/try_lock.distributed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package try_lock

import (
"fmt"
"math/rand"
"runtime"
"time"
)

type distributedTryLocker struct {
cmd CASCommand

key string
value string

option *options
}

type CASCommand interface {
CAS(key, src, dst string) bool
}

type Option func(*options)

func WithScheduleFunc(f func()) Option {
return func(o *options) {
o.schedule = f
}
}

type options struct {
schedule Schedule
}

type Schedule func()

func defaultSchedule() {
time.Sleep(time.Millisecond * time.Duration((rand.Intn(20)+1)*10))
runtime.Gosched()
}

func NewDistributedTryLocker(cmd CASCommand, key, value string, opts ...Option) TryMutexLocker {
option := &options{
schedule: defaultSchedule,
}
for _, opt := range opts {
opt(option)
}
return &distributedTryLocker{cmd: cmd, key: key, value: value, option: option}

}

func (r *distributedTryLocker) Unlock() {
r.cmd.CAS(r.key, r.value, "")
}

func (r *distributedTryLocker) TryLock(duration time.Duration) error {
if r.cmd.CAS(r.key, "", r.value) {
return nil
}
if duration > 0 {
timeoutChan := time.After(duration)
for {
select {
case <-timeoutChan:
return fmt.Errorf("%w: key=%s value=%s", errGetLockTimeOut, r.key, r.value)
default:
if r.cmd.CAS(r.key, "", r.value) {
return nil
}
// 执行一次切换调度
r.option.schedule()
}
}
}
return fmt.Errorf("%w: key=%s value=%s", errGetLockTimeOut, r.key, r.value)
}
45 changes: 45 additions & 0 deletions sync/try_lock/try_locker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package try_lock

import (
"errors"
"time"
)

type TryMutexLocker interface {
Unlock()
TryLock(duration time.Duration) error
}

type chMutex struct {
ch chan struct{}
}

func NewChMutex() TryMutexLocker {
return &chMutex{ch: make(chan struct{}, 1)}
}

var (
errGetLockTimeOut = errors.New("get lock timeout")
)

func (c *chMutex) TryLock(duration time.Duration) error {
if duration > 0 {
timeoutChan := time.After(duration)
select {
case <-timeoutChan:
return errGetLockTimeOut
case c.ch <- struct{}{}:
}
} else {
select {
case c.ch <- struct{}{}:
default:
return errGetLockTimeOut
}
}
return nil
}

func (c *chMutex) Unlock() {
<-c.ch
}

0 comments on commit 47367cd

Please sign in to comment.