Skip to content

Instantly share code, notes, and snippets.

@Petelin
Created February 28, 2020 11:06
Show Gist options
  • Save Petelin/6bc4f2cb062695c220a1c5307e4deb6a to your computer and use it in GitHub Desktop.
Save Petelin/6bc4f2cb062695c220a1c5307e4deb6a to your computer and use it in GitHub Desktop.
条件锁
package versionlock
import (
"errors"
"sync/atomic"
"time"
)
var ErrOldVersion = errors.New("old version")
var ErrUnlockFailed = errors.New("unlock failed")
type VLock struct {
version uint64
lock uint64
}
func (l *VLock) Lock(v uint64) error {
for {
version := atomic.LoadUint64(&l.version)
if v < version {
return ErrOldVersion
}
// new version try write to it
if !atomic.CompareAndSwapUint64(&l.version, version, v) {
// fail to write try again
continue
}
break
}
for {
lockV := atomic.LoadUint64(&l.lock)
version := atomic.LoadUint64(&l.version)
if v < version {
return ErrOldVersion
}
if lockV&1 == 1 {
time.Sleep(0)
continue
}
if atomic.CompareAndSwapUint64(&l.lock, lockV, lockV+3) {
return nil
}
}
}
func (l *VLock) UnLock() error {
lockV := atomic.LoadUint64(&l.lock)
if !atomic.CompareAndSwapUint64(&l.lock, lockV, lockV-1) {
return ErrUnlockFailed
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment