Skip to main content
Code Review

Return to Question

deleted 8 characters in body; edited title
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

Is my spin Spin-lock implementation correct?

I'm working on a project where a spinlock is more appropriate than a mutex, and after few tries I came up with:

type SpinLock uint32
func (sl *SpinLock) Lock() {
 for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
 runtime.Gosched() //without this it locks up on GOMAXPROCS > 1
 }
}
func (sl *SpinLock) Unlock() {
 atomic.StoreUint32((*uint32)(sl), 0)
}

It works fine, and it's even a little bit faster than sync.Mutex, and 2x the speed of sync.RWMutex.

➜ go test -bench=. -benchmem -v -cpu 4
BenchmarkSpinL-4 2000 1078798 ns/op 33923 B/op 2006 allocs/op
BenchmarkMutex-4 2000 1195814 ns/op 32781 B/op 2002 allocs/o
BenchmarkRWMutex-4 1000 2352117 ns/op 78253 B/op 2147 allocs/op

The test uses multi readers / writers to a map[int]*struct{int, int}, , running. Running it with -race doesn't detect any data races, either.

But I have that nagging feeling that I forgot something, so I'm wondering if my implementation is correct?

Is my spin-lock implementation correct?

I'm working on a project where a spinlock is more appropriate than a mutex, and after few tries I came up with:

type SpinLock uint32
func (sl *SpinLock) Lock() {
 for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
 runtime.Gosched() //without this it locks up on GOMAXPROCS > 1
 }
}
func (sl *SpinLock) Unlock() {
 atomic.StoreUint32((*uint32)(sl), 0)
}

It works fine, and it's even a little bit faster than sync.Mutex, and 2x the speed of sync.RWMutex.

➜ go test -bench=. -benchmem -v -cpu 4
BenchmarkSpinL-4 2000 1078798 ns/op 33923 B/op 2006 allocs/op
BenchmarkMutex-4 2000 1195814 ns/op 32781 B/op 2002 allocs/o
BenchmarkRWMutex-4 1000 2352117 ns/op 78253 B/op 2147 allocs/op

The test uses multi readers / writers to a map[int]*struct{int, int}, , running it with -race doesn't detect any data races, either.

But I have that nagging feeling that I forgot something, so I'm wondering if my implementation is correct?

Spin-lock implementation

I'm working on a project where a spinlock is more appropriate than a mutex, and after few tries I came up with:

type SpinLock uint32
func (sl *SpinLock) Lock() {
 for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
 runtime.Gosched() //without this it locks up on GOMAXPROCS > 1
 }
}
func (sl *SpinLock) Unlock() {
 atomic.StoreUint32((*uint32)(sl), 0)
}

It works fine, and it's even a little bit faster than sync.Mutex, and 2x the speed of sync.RWMutex.

➜ go test -bench=. -benchmem -v -cpu 4
BenchmarkSpinL-4 2000 1078798 ns/op 33923 B/op 2006 allocs/op
BenchmarkMutex-4 2000 1195814 ns/op 32781 B/op 2002 allocs/o
BenchmarkRWMutex-4 1000 2352117 ns/op 78253 B/op 2147 allocs/op

The test uses multi readers / writers to a map[int]*struct{int, int}. Running it with -race doesn't detect any data races, either.

But I have that nagging feeling that I forgot something, so I'm wondering if my implementation is correct?

Tweeted twitter.com/#!/StackCodeReview/status/501182733478277120
edited tags
Link
200_success
  • 145.5k
  • 22
  • 190
  • 478
grammar is highly overrated.
Source Link
OneOfOne
  • 355
  • 3
  • 12

I'm working on a project where a spinlock is more appropriate than a mutex, and after few tries I came up with:

type SpinLock uint32
func (sl *SpinLock) Lock() {
 for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
 runtime.Gosched() //without this it locks up on GOMAXPROCS > 1
 }
}
func (sl *SpinLock) Unlock() {
 atomic.StoreUint32((*uint32)(sl), 0)
}

It works fine, and it's even a little bit faster than sync.Mutex, and 2x the speed of sync.RWMutex.

➜ go test -bench=. -benchmem -v -cpu 4
testing: warning: no tests to run
PASS
BenchmarkSpinL-4 2000 1078798 ns/op 33923 B/op 2006 allocs/op
BenchmarkMutex-4 2000 1195814 ns/op 32781 B/op 2002 allocs/o
BenchmarkRWMutex-4 1000 2352117 ns/op 78253 B/op 2147 allocs/op

The test uses multi readers / writers to a map[int]*struct{int, int}, , running it with -race doesn't detect any data races, either.

But I have that nagging feeling that I forgot something, so I'm wonderwondering if my implementation is correct?

I'm working on a project where a spinlock is more appropriate than a mutex, and after few tries I came up with:

type SpinLock uint32
func (sl *SpinLock) Lock() {
 for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
 runtime.Gosched() //without this it locks up on GOMAXPROCS > 1
 }
}
func (sl *SpinLock) Unlock() {
 atomic.StoreUint32((*uint32)(sl), 0)
}

It works fine, and it's even a little bit faster than sync.Mutex, and 2x the speed of sync.RWMutex.

➜ go test -bench=. -benchmem -v -cpu 4
testing: warning: no tests to run
PASS
BenchmarkSpinL-4 2000 1078798 ns/op 33923 B/op 2006 allocs/op
BenchmarkMutex-4 2000 1195814 ns/op 32781 B/op 2002 allocs/o
BenchmarkRWMutex-4 1000 2352117 ns/op 78253 B/op 2147 allocs/op

The test uses multi readers / writers to a map[int]*struct{int, int}, , running it with -race doesn't detect any data races, either.

But I have that nagging feeling that I forgot something, so I'm wonder if my implementation is correct?

I'm working on a project where a spinlock is more appropriate than a mutex, and after few tries I came up with:

type SpinLock uint32
func (sl *SpinLock) Lock() {
 for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
 runtime.Gosched() //without this it locks up on GOMAXPROCS > 1
 }
}
func (sl *SpinLock) Unlock() {
 atomic.StoreUint32((*uint32)(sl), 0)
}

It works fine, and it's even a little bit faster than sync.Mutex, and 2x the speed of sync.RWMutex.

➜ go test -bench=. -benchmem -v -cpu 4
BenchmarkSpinL-4 2000 1078798 ns/op 33923 B/op 2006 allocs/op
BenchmarkMutex-4 2000 1195814 ns/op 32781 B/op 2002 allocs/o
BenchmarkRWMutex-4 1000 2352117 ns/op 78253 B/op 2147 allocs/op

The test uses multi readers / writers to a map[int]*struct{int, int}, , running it with -race doesn't detect any data races, either.

But I have that nagging feeling that I forgot something, so I'm wondering if my implementation is correct?

Source Link
OneOfOne
  • 355
  • 3
  • 12
Loading
lang-golang

AltStyle によって変換されたページ (->オリジナル) /