多线程协作免不了使用计数器,
通常的代码,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(使用前将#替换为@)