Go如何实现自旋锁

自旋锁简介

在并发编程中,互斥锁(Mutex)是一种常用的同步机制,用于保护临界资源,防止数据竞争。而在某些特定场景下,尤其是当锁的持有时间很短且线程数量有限的情况下,一种更为轻量级的锁------自旋锁(Spin Lock)可以提供更高的性能。

什么是自旋锁

自旋锁是一种忙等待锁,当一个线程尝试获取一个已经被其它线程持有的锁时,这个线程会持续循环检查锁的状态(即"自旋") ,直到锁被释放后获得所有权。这种等待方式避免了线程上下文切换带来的开销,因此比较适用于锁竞争不激烈且锁定时间非常短的场景。

自旋锁原理

当一个线程尝试获取自旋锁时,如果发现锁已被占用,则该线程会进入一个循环,不断检查锁是否已被释放。一旦锁的持有者完成操作并释放锁后,正在自旋的线程即可立即获得锁并继续执行。

自旋锁的优缺点

避免了线程切换和调度的开销,持锁时间短性能好

持锁时间长或锁竞争频繁会导致CPU

如何选择合适的锁

如果不确定锁的持有时间,则选择互斥锁或者读写锁

如果确定锁的持有时间很短,则可以考虑使用自旋锁

如果读操作比较比多,则优先考虑读写锁

自旋锁实例

go 复制代码
package main

import (
	"log"
	"sync"
	"sync/atomic"
)

func init() {
	log.SetFlags(log.LstdFlags)
}

type SpinLock struct {
	state int32
}

func (s *SpinLock) Lock() {
	for !atomic.CompareAndSwapInt32(&s.state, 0, 1) {
		//自旋,不执行任何操作
	}
}
func (s *SpinLock) unLock() {
	atomic.StoreInt32(&s.state, 0)
}
func main() {
	var cnt int
	spinLock := SpinLock{}
	wg := sync.WaitGroup{}

	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			spinLock.Lock()
			cnt++
			spinLock.unLock()
			wg.Done()
		}()
	}
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			spinLock.Lock()
			cnt++
			spinLock.unLock()
			wg.Done()
		}()
	}
	wg.Wait()
	log.Println("cnt:", cnt)
}
相关推荐
有代理ip1 天前
Python 与 Golang 爬虫的隐藏优势
爬虫·python·golang
天远云服1 天前
天远车辆过户查询API微服务实战:用Go语言构建高性能车况溯源系统
大数据·微服务·架构·golang
女王大人万岁1 天前
Go标准库 sync 详解
服务器·开发语言·后端·golang
小高Baby@1 天前
session、cookie、Jwt-token
开发语言·后端·golang
Grassto1 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
小二·1 天前
Go 语言系统编程与云原生开发实战(第12篇)云原生部署实战:Helm Chart × GitOps × 多环境管理(生产级落地)
开发语言·云原生·golang
天空属于哈夫克31 天前
Go 语言实战:构建一个企微外部群“技术贴收藏夹”小程序后端
小程序·golang·企业微信
小二·1 天前
Go 语言系统编程与云原生开发实战(第13篇)工程效能实战:Monorepo × 依赖治理 × 构建加速(10万行代码实测)
开发语言·云原生·golang
暴躁小师兄数据学院1 天前
【WEB3.0零基础转行笔记】Golang编程篇-第4讲:Go语言中的流程控制
开发语言·后端·golang·web3·区块链
lingggggaaaa2 天前
安全工具篇&Go魔改二开&Fscan扫描&FRP代理&特征消除&新增扩展&打乱HASH
学习·安全·web安全·网络安全·golang·哈希算法