多线程如何实现高性能计数器(无锁)

2023-05-16

多线程协作免不了使用计数器,

通常的代码,c++一般会使用锁,或者原子变量操作:

std::mutex mutexCounter;
int count;


void add()
{
    std::lock_guard<std::mutex> guard(mutexCounter);
    count ++;
}
std::atomic<int> count;

void add()
{

    count ++;
}

在性能要求比较高的情况下,这样的代码100%是整个业务的瓶颈;

那么如何优化?答案是让线程写到自己的计数内,在计算总和时候再使用锁来汇总一次;

方法一:

可以每个线程分配一个0-N (64个左右)的索引号,通过索引去访问计数单元中的对应的的槽位,这样线程之间不会相互影响,就实现了无锁写入;读的时候可以根据对精度的要求来确定是否需要加锁同步统计:

#pragma once
#include <thread>
#include <mutex>
#include <map>
#include <vector>

class VarBase
{
public:
	static int getIndex();

private:
	static int cusor;
	static thread_local int index;
	//static std::map<std::thread::id, int> idMap;
	static std::mutex mutexMap;

};

class VarSingle
{
public:
	VarSingle() : data(64)
	{

	}

	inline int setData(int val)
	{
		int index = VarBase::getIndex();
		if (index >= data.size())
		{
			std::lock_guard<std::mutex> gurad(mutexVec);
			if (index >= data.size())
				data.resize(data.size() + 16);
		}
		data[index] = val;
		return index;
	}

	int getVal()
	{
		int index = VarBase::getIndex();
		if (index >= data.size())
			return 0;

		return data[index];
	}

	int64_t getSum(bool precise)
	{
		int64_t all = 0;
		if (precise)
		{
			std::lock_guard<std::mutex> gurad(mutexVec);
			for (size_t i = 0; i < data.size(); i++)
			{
				all += data[i];
			}
		}
		else
		{
			for (size_t i = 0; i < data.size(); i++)
			{
				all += data[i];
			}
		}

		return all;
	}

	void reset()
	{
		std::lock_guard<std::mutex> gurad(mutexVec);
		for (size_t i = 0; i < data.size(); i++)
		{
			data[i] = 0;
		}
	}

private:
	std::vector<int> data;
	std::mutex mutexVec;
};


// Var.cpp
#include "Var.h"


int VarBase::index = -1;
int VarBase::cusor = 0;
int VarBase::getIndex()
{
	if (index == -1)
	{
		std::lock_guard<std::mutex>  guard(mutexMap);
		index = cusor++;
		
	}

	return index;
}

第二种:

可以设置全局的一个map信息,

Var的构造函数,将自己的线程局部存储的指针注册到全局信息中,在析构时候删除注册信息;

这样,每次写数据都写到线程本地存储中,而统计时候通过全局注册信息汇总;

代码,略;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多线程如何实现高性能计数器(无锁) 的相关文章

  • python 的 do ~ while 语法

    本文摘至 http ama ch hatenablog com entry 20080425 1209110237 Python不支持do while语法 while xff08 无限循环 xff09 和break组合起来替换 do whi
  • 802.11协议帧格式、Wi-Fi连接交互过程、无线破解入门研究

    本文转载至 xff1a http www cnblogs com littlehann p 3700357 html 目录 1 802 11标准简介 2 802 11协议格式 3 Wi Fi认证过程 4 802 11标准中的数据安全加密协议
  • Make 命令教程

    转载至 xff1a http www ruanyifeng com blog 2015 02 make html 作者 xff1a 阮一峰 日期 xff1a 2015年2月20日 代码变成可执行文件 xff0c 叫做编译 xff08 com
  • Python中用于计算对数的log()方法

    本文转载至 xff1a http www jb51 net article 66130 htm 这篇文章主要介绍了Python中用于计算对数的log 方法 是Python入门基础中的必会的方法 需要的朋友可以参考下 log 方法返回x的自然
  • RT-Thread创始人熊谱翔: 我和Linux、嵌入式实时操作系统RT-Thread

    本文转载至 xff1a http www rt thread org dynamic 78 html 接触 Linux 说起 Linux应该从我在校园时期说起 我是在山城 重庆邮电学院念的书 xff0c 1998年时宿舍伙伴一起凑的钱买的电
  • 到底什么是Unikernel?

    本文转载至 xff1a http dockone io article 855 utm source 61 tuicool amp utm medium 61 referral 编者的话 本文介绍了一种新的应用虚拟化技术 xff0c 它让应
  • xauth: “timeout in locking authority file /home/<user>/.Xauthority”?

    本文转载至 xff1a http unix stackexchange com questions 215558 why am i getting this message from xauth timeout in locking aut
  • 小技巧:检查你本地及公共 IP 地址

    本文转载至 xff1a https linux cn article 8207 1 html utm source 61 rss amp utm medium 61 rss 你本地的 IP 地址 xff1a 192 168 1 100 上面
  • Inside Real-Time Linux

    本文转载于 xff1a https www linux com news event elce 2017 2 inside real time linux Real time Linux has come a long way in the
  • [小技巧] vim中使用cscope时不区别大小写

    cscope 有 C 这么一个选项 C Ignore letter case when searching vim 里使用 cscope 不区别大小写可以使用下面一个技巧 xff1a set csprg 61 usr bin ra csco
  • PWM占空比和电机转速有什么线性关系

    可以看电机拖动一书 xff0c 里面讲了电机的建模 由于PWM波频率很高 xff0c 一般认为接在电机两端的电压平均值有如下关系 xff1a 假如占空比为a xff0c 驱动板供电电压为U xff0c 则电机两端电压Ud 61 a U 对于
  • SIFT特征点提取及描述论文算法详解

    SIFT特征点提取及描述论文算法详解 1 尺度空间极值检测 Scale space extrema detection 1 1 尺度空间和极值1 2 DoG和LoG的关系1 3 构建高斯尺度差分空间Tips 2 极值点定位 Keypoint
  • 国科大计算机视觉20-21考题

    国科大计算机视觉20 21考题 SIFT检测及描述流程 xff08 20分 xff09 相机成像模型 xff08 16分 xff09 两视图的稀疏重建 xff08 16分 xff09 LM算法流程 xff08 16分 xff09 PCA的思
  • Ubuntu18.04关闭内核自动更新安装之前版本

    Ubuntu18 04关闭内核自动更新安装之前版本 回退的原因 xff0c 上一周安装了Ubuntu18 04双系统 xff0c 主机型号是外星人 Asura R6 xff0c 安装完毕后可以正常进入Ubuntu xff0c 但是关机的时候
  • Windows10配置MongoDB

    Windows10安装MongoDB并配置 1 安装2 安装完成后启动服务器2 1 一次性启动2 2 设置为服务 xff0c 开机自启动 3 添加环境变量 xff0c 方便在cmd任何目录中直接启动 参考链接 xff1a https www
  • Ubuntu18.04编译ORB-SLAM3及遇到的一些问题

    测试环境 xff1a 系统 xff1a Ubuntu18 04Eigen 3 3 4 查看Eigen3版本的方法Pangolin 0 6OpenCV 3 4 14ROS Melodic 一 安装依赖 ORB SLAM的各项依赖里OpenCV
  • Python multiprocessing多进程编程,进程间通信,psutil监控进程状态并通过电子邮件告警

    python多进程编程 进程监测 一 mutiprocessng多进程编程和通信二 进程监测分析 三 Python邮件发送功能四 完整代码运行结果 xff1a 服务器上的web后端经常需要同时运行多个进程 xff0c 各个进程之间需要交换数
  • Supervisor服务器进程监测

    服务器上的应用程序有时候会莫名其妙地挂掉 xff0c 如果我们经常去登录服务器看是不是程序挂了 xff0c 挂了再拉起 xff0c 那样是非常耗时和麻烦的事情 后来我们通过使用 supervisor 去守护启动 xff0c 实现方法如下 一
  • Ubuntu18.04手动安装NVIDIA驱动

    Ubuntu18 04手动安装NVIDIA驱动 1 下载驱动 查看系统推荐的驱动版本 xff0c 官网下载对应的run文件 NVIDIA驱动下载的高级搜索 xff1a https www nvidia cn Download Find as
  • ORB-SLAM2 编译记录

    ORB SLAM2编译记录 由于之前已经编译过ORB SLAM3 xff0c 大部分库都已经配置好了 xff0c 这次主要只了处理两个错误 1 error usleep is not declared in this scope xxx x

随机推荐