引言
在系统实现的过程中,经常需要用到计数功能,为了多线程下的安全使用,我自己定义了一个原子类。
基于Mutex的实现
我基于Mutex实现了一个简单的原子类,代码如下
/*
* 说明:自定义整数操作的原子类,减少代码中的各种锁
*/
#ifndef _ATOMIC_INT64_H_
#define _ATOMIC_INT64_H_
#include <stdint.h>
#include "mutex.h"
template<class T>
class AtomicInt
{
public:
AtomicInt(T value_) : value(value_){};
//自增长操作,返回增长前的值
void Increment(const T& step)
{
MutexGuard guard(mutex);
value += step;
}
T GetValue()
{
MutexGuard guard(mutex);
return value;
}
private:
T value;
Mutex mutex;
};
#endif
如代码所示,这是一种最简单的原子类实现方式,基于系统提供的互斥量,实现对变量的互斥访问。
C++11下的原子锁
C++11本身提供了原子锁供我们使用,非常方便,我写代码测试了一下,确实有效。 测试代码采用多线程分别对atomic int类型和普通的整数类型进行自增操作。结果发现 atomic int结果正确,而普通int类型数据不正确。
atomic_int32_t atomicintparam = 0;
int32_t intparam = 0;
void thread_atomic_test()
{
for (int i = 0; i < 10000; i++)
{
atomicintparam++;
intparam++;
}
}
void AtomicParamTest()
{
vector<thread*> threads;
for (int i = 0; i < 10; i++)
{
std::thread* task = new std::thread(thread_atomic_test);
threads.push_back(task);
}
for (thread* task : threads)
{
task->join();
}
cout << "atomic int param: " << atomicintparam << endl;
cout << "common int param: " << intparam << endl;
}
结果如下:
atomic int param: 100000
common int param: 86996
目前的情况是我们的编译器不支持C++11, 但是我觉得基于Mutex实现一个原子锁又过重。为了解惑,我做了一个测试,在10个线程的并发下对某个整数进行自增操作,加到1亿。测试下来的时间如下,单位毫秒:
atomic int param: 100000000(自增次数) 2969 (时间)
atomic int param: 100000000(自增次数) 13187(时间)
测试结果发现相差4倍左右,单线程加到1千万需要13s,我的场景里每个计数器计数不超过100,用mutex,还没有成为我的瓶颈,可以使用。