diff --git a/internal/spinlock.go b/internal/spinlock.go index af8b55f..5e8572c 100644 --- a/internal/spinlock.go +++ b/internal/spinlock.go @@ -12,13 +12,18 @@ import ( type spinLock uint32 +const maxBackoff = 64 + func (sl *spinLock) Lock() { backoff := 1 for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) { + // Leverage the exponential backoff algorithm, see https://en.wikipedia.org/wiki/Exponential_backoff. for i := 0; i < backoff; i++ { runtime.Gosched() } - backoff <<= 1 + if backoff < maxBackoff { + backoff <<= 1 + } } } diff --git a/internal/spinlock_test.go b/internal/spinlock_test.go index 168010b..27d57ab 100644 --- a/internal/spinlock_test.go +++ b/internal/spinlock_test.go @@ -11,6 +11,17 @@ import ( "testing" ) +/* +Benchmark result for three types of locks: + goos: darwin + goarch: amd64 + pkg: github.com/panjf2000/ants/v2/internal + cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz + BenchmarkMutex-12 20549502 71.84 ns/op 0 B/op 0 allocs/op + BenchmarkSpinLock-12 58629697 20.02 ns/op 0 B/op 0 allocs/op + BenchmarkBackOffSpinLock-12 72523454 15.74 ns/op 0 B/op 0 allocs/op +*/ + type originSpinLock uint32 func (sl *originSpinLock) Lock() {