栈:基本的数据结构之一,有先进后出的特性。
当栈用于多线程程序的时候,必须要为其加上锁保护才能避免重入的问题。
在多线程程序中,在调用栈的地方加锁,完成后再解锁,这可能导致程序复杂,而且在很多地方会涉及到加锁解锁等操作,很难维护。
正确的方式是在操作函数内部直接加锁,或再用函数对加锁过程进行封装,其他函数直接使用具有加锁和解锁功能的函数是最理想的。
下面的程序封装了一个有锁功能的栈的数据结构。
mt_stack.h
#include <pthread.h>
#ifndef __MT_STACK_H__
#define __MT_STACK_H__
typedef struct _Stack_st
{
void ** m_ppBase;
unsigned int m_uTop;
unsigned int m_uStackSize;
} Stack_st;
typedef struct _MTStack_st
{
Stack_st *m_Stack;
pthread_mutex_t m_Lock;
} MTStack_st;
class MT_Stack
{
public:
MT_Stack(unsigned int nStackSize);
int Push(void *pData);
void* Pop();
~MT_Stack();
private:
MTStack_st * m_pMTStack;
};
#endif
mt_stack.cpp
#include <iostream>
#include "mt_stack.h"
using namespace std;
MT_Stack::MT_Stack(unsigned int nStackSize)
{
if (nStackSize == 0)
{
return;
}
cout << "Create MT_Stack" << endl;
m_pMTStack = (MTStack_st*) malloc(sizeof(MTStack_st));
m_pMTStack->m_Stack = (Stack_st*) malloc(sizeof(Stack_st));
if (m_pMTStack != NULL)
{
m_pMTStack->m_Stack->m_ppBase
= (void**)malloc(nStackSize*sizeof(void*));
if (m_pMTStack->m_Stack->m_ppBase == NULL)
{
free(m_pMTStack);
m_pMTStack = NULL;
}
else
{
m_pMTStack->m_Stack->m_ppBase[0] = NULL;
m_pMTStack->m_Stack->m_uTop = 0;
m_pMTStack->m_Stack->m_uStackSize = nStackSize;
}
}
pthread_mutex_init(&m_pMTStack->m_Lock, NULL);
}
MT_Stack::~MT_Stack()
{
int i = 0;
if (m_pMTStack == NULL)
return;
cout << "Destroy MT_Stack" << endl;
if (m_pMTStack->m_Stack->m_ppBase != NULL)
{
for (i = 0; i < m_pMTStack->m_Stack->m_uStackSize; i++)
{
free(m_pMTStack->m_Stack->m_ppBase[i]);
}
free(m_pMTStack->m_Stack->m_ppBase);
}
pthread_mutex_destroy(&m_pMTStack->m_Lock);
free(m_pMTStack);
}
void* MT_Stack::Pop()
{
void* pData;
if ((NULL == m_pMTStack) || (0 == m_pMTStack->m_Stack->m_uTop))
{
return NULL;
}
cout << "pop pre_lock" << endl;
pthread_mutex_lock(&m_pMTStack->m_Lock);
m_pMTStack->m_Stack->m_uTop -= 1;
pData = m_pMTStack->m_Stack->m_ppBase[m_pMTStack->m_Stack->m_uTop];
pthread_mutex_unlock(&m_pMTStack->m_Lock);
cout << "pop un_lock" << endl;
return pData;
}
int MT_Stack::Push(void* pData)
{
if (NULL == m_pMTStack)
{
return 0;
}
// The Stack is full
if (m_pMTStack->m_Stack->m_uTop >= m_pMTStack->m_Stack->m_uStackSize -1)
{
return 0;
}
cout << "push pre_lock" << endl;
pthread_mutex_lock(&m_pMTStack->m_Lock);
m_pMTStack->m_Stack->m_ppBase[m_pMTStack->m_Stack->m_uTop] = pData;
m_pMTStack->m_Stack->m_uTop ++;
pthread_mutex_unlock(&m_pMTStack->m_Lock);
cout << "push un_lock" << endl;
return m_pMTStack->m_Stack->m_uTop;
}
Here in push and pop function, we add the lock and unlock the stack.
源代码及测试结果:http://download.csdn.net/detail/wangzhiyu1980/4693293