CAS算法是一种有名的无锁算法, 在不使用锁的情况下实现多线程之间的变量同步,而且没有堵塞线程.
CAS基本步骤如下: 需要读写的内存值V==>进行比较的值A==>拟写入的新值B
当且仅当 V 的值等于 A时,CAS通过原子方式用新值B来更新V的值;
否则不会执行任何操作(比较和替换是一个原子操作)。
自旋锁是指当一个线程在获取锁的时候,如果锁已经被其他线程获取,那么该线程将循环等待,然后不断地判断是否能够被成功获取,直到获取到锁才会退出循环。通过死循环检测锁的标志位, 避免了上下文切换的开销, 但是自旋会消耗CPU资源。
自旋锁就主要用在临界区持锁时间非常短且CPU资源不紧张的情况下,自旋锁一般用于多核的服务器。
对于线程A和线程B来讲,在同一时刻,只允许一个线程对临界资源进行操作,即当A加锁进入临界区对资源操作时,B就必须等待;当A执行完释放锁,退出临界区后,B才能对临界资源进行操作。线程会从 sleep(加锁)—>running(解锁),过程中有上下文的切换,cpu的抢占,信号的发送等开销。
所以一般用于临界区持锁时间比较长的操作。
go官方提供了atomic
算法相关的包, 我们可以使用它直接实现一个自旋锁
package main
import (
"runtime"
"sync"
"sync/atomic"
)
type originSpinLock uint32
func (sl *originSpinLock) Lock() {
for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
runtime.Gosched()
}
}
func (sl *originSpinLock) Unlock() {
atomic.StoreUint32((*uint32)(sl), 0)
}
func NewOriginSpinLock() sync.Locker {
return new(originSpinLock)
}
package main
import (
"runtime"
"sync"
"sync/atomic"
)
type spinLock uint32
const maxBackoff = 16
// Lock 加锁
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()
}
if backoff < maxBackoff {
backoff <<= 1
}
}
}
// Unlock 解锁
func (sl *spinLock) Unlock() {
atomic.StoreUint32((*uint32)(sl), 0)
}
// NewSpinLock instantiates a spin-lock.
func NewSpinLock() sync.Locker {
return new(spinLock)
}
package main
import "testing"
func BenchmarkOriginSpinLock(b *testing.B) {
spin := NewOriginSpinLock()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
spin.Lock()
//nolint:staticcheck
spin.Unlock()
}
})
}
func BenchmarkSpinLock(b *testing.B) {
spin := NewSpinLock()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
spin.Lock()
//nolint:staticcheck
spin.Unlock()
}
})
}
测试结果
goos: darwin
goarch: amd64
pkg: github.com/guirongguo/ghz_demo
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkOriginSpinLock
BenchmarkOriginSpinLock-12 47265601 21.54 ns/op
BenchmarkSpinLock
BenchmarkSpinLock-12 66324406 18.29 ns/op
《自旋锁》
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。