当前位置: 首页 > article >正文

Go如何实现自旋锁

自旋锁简介

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

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

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

自旋锁的优缺点

避免了线程切换和调度的开销,持锁时间短性能好
持锁时间长或锁竞争频繁会导致CPU

如何选择合适的锁

如果不确定锁的持有时间,则选择互斥锁或者读写锁
如果确定锁的持有时间很短,则可以考虑使用自旋锁
如果读操作比较比多,则优先考虑读写锁

自旋锁实例

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)
}


http://www.kler.cn/a/374934.html

相关文章:

  • mysql中的锁理解
  • 2024年北京市安全员-A证证模拟考试题库及北京市安全员-A证理论考试试题
  • FineReport 单元格的特殊应用场景
  • 百度如何打造AI原生研发新范式?
  • 界面控件DevExpress WPF中文教程:Data Grid——卡片视图概述
  • 驱动——线程断链和信息获取
  • 【项目小技巧】【C++】 Debug 日志输出 调用者的函数名,所在文件名和行号
  • C语言学,标准库 <string.h>
  • 自适应神经网络架构:原理解析与代码示例
  • 操作系统期中复习第一单元
  • Docker部署教程:打造流畅的斗地主网页小游戏
  • 大数据新视界 -- 大数据大厂之大数据环境下的网络安全态势感知
  • 访问jenkins页面报错
  • 5G三大应用场景中的URLLC
  • 全新大模型框架Haystack,搭建RAG pipeline
  • 从零开始的C++之旅——string类的模拟实现
  • 【Git】Git常用命令
  • (蓝桥杯C/C++)——常用库函数
  • 【Deno运行时】深入解析Deno:下一代JavaScript和TypeScript运行时
  • cisco网络安全技术第4章测试及考试
  • 高效扶贫:SpringBoot精准扶贫系统
  • 笔记整理—linux驱动开发部分(4)驱动框架
  • 【Nginx】编译安装(Centos)
  • Windows下Jenkins自动启动jar包
  • 技术总结(十九)
  • unity后端kbengine用DOTween让 移动同步丝滑