原子计数器 for Pthreads

在多线程环境下要计数,需要保证:计数变量的一致性和线程安全才能保证多线程环境下计数正确。

原子计数正是提供了此需求的功能,保证计数操作未执行完毕时绝不会被其他任何实务或事件打断,下面是原子计数器 for pthreads


缺点:使用锁的形式实现原子计数时锁的操作会比计数器的加减操作的消耗大很多,可以通过linux自带的性能检测工具perf命令查看哪些操作消耗多。

#ifndef __ATOMICCOUNTER_H__
#define __ATOMICCOUNTER_H__

#if defined(__linux__)
//CAtomicCounter.h for Pthreads
#include <pthread.h>
	
class CAtomicCounter 
{
private:
	class CGuard //pthread_mutex_t锁的守护者类CGuard	
	{
	public:
		CGuard(pthread_mutex_t & mutex):m_mutex(mutex)
		{
			pthread_mutex_lock(&m_mutex);
		}
		~CGuard()
		{
			pthread_mutex_unlock(&m_mutex);
		}
	private:
		pthread_mutex_t	m_mutex;
	};

private:
	CAtomicCounter(CAtomicCounter const&);//禁止拷贝构造
	CAtomicCounter& operator=(CAtomicCounter const&);//禁止赋值构造

public:
	/// 需要显示调用此构造函数,阻止使用编译器提供的默认构造函数
	explicit CAtomicCounter(long n) : m_cnt(n)	
	{
		pthread_mutex_init(&m_mutex, 0);
	}
	~CAtomicCounter()
	{
		pthread_mutex_destroy(&m_mutex);
	}
	long operator++()
	{
		CGuard guard(m_mutex);
		return ++m_cnt;
	}
	long operator--()
	{
		CGuard guard(m_mutex);
		return --m_cnt;
	}
	operator long() const
	{
		CGuard guard(m_mutex);
		return m_cnt;
	}
	
private:
	//如果没有mutable,operator long() const编译会失败
	//const成员函数operator long()里面是不能修改变量的值的
	//其第一行CGuard guard(m_mutex);的入参要求为非const类型
	//如果把m_mutex声明为mutable类型,可以摆脱const成员函数的
	//不能修改变量的特性,
	//这么一来m_mutex通过mutable的修饰摆脱const成员函数的限制可以作为非const变量作为guard()的入参
	mutable pthread_mutex_t m_mutex; 
	long	m_cnt;
};
#endif //#if defined(__linux__)

#endif


usage测试用例:

#include "AtomicCounter.h"
#include <iostream>

using namespace std;

int main()
{
	CAtomicCounter atomic(1);
	++atomic;
	cout<<__FILE__<<":"<<__LINE__<<":"<<__FUNCTION__<<(long)atomic<<endl;
	--atomic;
	cout<<__FILE__<<":"<<__LINE__<<":"<<__FUNCTION__<<(long)atomic<<endl;
}

多线程测试用例:


(END)

你可能感兴趣的:(原子计数器 for Pthreads)