现在公司的代码动不动各种崩溃,原因大部分是由不加锁引起的。
例如很多的底层数据,全部封装成了AfxGetXXX的形式,对所有的类,模块全部暴露:
例如,一个缓存类,DataCache, 其中有个std::map保存数据,那么会有一个全局的AfxGetDataCache()返回这个数据结构,其中居然提供了接口std::map<CLS> &GetCache()接口,所以导致了多线程中直接操作数据引起崩溃的风险,实际也是经常会崩溃。
无奈这些东西历史已久,而且涉及太广,改动是很难了,除非有一个专门的时间来重构,现在记下来引以为戒。
并附上一段自己的代码,时刻警示自己。
</pre><pre name="code" class="cpp">#include <afxmt.h>
#include <time.h>
#include <stdlib.h>
#include <vector>
#include <atldbcli.h>
class ThreadSyncClassBase;
struct OpParam
{
OpParam(ThreadSyncClassBase *ptest,int operate):ptest_(ptest),operate_(operate){}
ThreadSyncClassBase *ptest_;
int operate_;
};
class ThreadSyncClassBase
{
public:
ThreadSyncClassBase()
{
TCHAR lockname[20] = {};
_stprintf_s(lockname,_countof(lockname),_T("data_0x%08x"),this);
plock_data_ = new CMutex(FALSE,lockname);
}
~ThreadSyncClassBase()
{
plock_data_->Lock();
delete plock_data_;
}
void InsertData()
{
plock_data_->Lock();
data_.push_back(rand()%1000);
plock_data_->Unlock();
}
void DeleteTailData()
{
plock_data_->Lock();
if (!data_.empty())
{
data_.erase(data_.end()-1);
}
plock_data_->Unlock();
}
int GetHeadData()
{
int ret = 0;
plock_data_->Lock();
if (!data_.empty())
{
ret = data_.front();
}
plock_data_->Unlock();
return ret;
}
//不应该出现这样的接口!!!
std::vector<int> &Datas()
{
return data_;
}
//正常可能出现的线程操作
static void OperateFunc(void *param)
{
OpParam * pparam = reinterpret_cast<OpParam*>(param);
ThreadSyncClassBase * pthis = pparam->ptest_;
int operate = pparam->operate_;
switch(operate)
{
case 0:{for(int i = 0; i < 100000; ++i){pthis->InsertData() ;}}break;
case 1:{for(int i = 0; i < 100000; ++i){pthis->DeleteTailData() ;}}break;
case 2:{for(int i = 0; i < 100000; ++i){pthis->GetHeadData() ;}}break;
}
}
//死锁情况
static void DeadLockTest(void *param)
{
OpParam * pparam = reinterpret_cast<OpParam*>(param);
ThreadSyncClassBase * pthis = pparam->ptest_;
pthis->plock_data_->Lock();
Sleep(10000);
// pthis->plock_data_->Unlock();//没有了
}
protected:
CMutex *plock_data_;
std::vector<int> data_;
};
class SingleInstanceClass : public ThreadSyncClassBase
{
private:
SingleInstanceClass(){}
~SingleInstanceClass(){}
public:
static SingleInstanceClass *GetInstance(){if(pInst == NULL){pInst = new SingleInstanceClass;}return pInst;}
static void ReleaseInstance(){delete pInst;pInst = NULL;}
private:
static SingleInstanceClass *pInst;
};
SingleInstanceClass *SingleInstanceClass::pInst = NULL;
class MultiplyInstanceClass : public ThreadSyncClassBase
{
};
//线程函数在类外,只读取类中的数据,线程执行过程中,类对象被释放
void OuterFuncProc(void *param)
{
OpParam * pparam = reinterpret_cast<OpParam*>(param);
ThreadSyncClassBase * pthis = pparam->ptest_;
std::vector<int> &vct = pthis->Datas();
while(1)
{
int randnum = rand()%2;
switch(randnum)
{
case 0:{vct.push_back(rand()%1000);}break;
case 1:{if (!vct.empty()){vct.erase(vct.end()-1);}}break;
}
}
}
void TestThreadSyncSingleinstance()
{
int count = 6;
SingleInstanceClass * pTestCls = NULL;
OpParam **opparam_array = new OpParam *[count];
HANDLE *handle_array = new HANDLE[count];
for (int i = 0; i < count; ++i)
{
pTestCls = SingleInstanceClass::GetInstance();
opparam_array[i] = new OpParam(pTestCls,i%3);
handle_array[i] = HANDLE(_beginthread(ThreadSyncClassBase::OperateFunc,0,reinterpret_cast<void*>(opparam_array[i])));
Sleep(1234);
}
//{{
OpParam paramouterlock(pTestCls,1);
_beginthread(OuterFuncProc,0,¶mouterlock);
Sleep(1000);
//}}
pTestCls->ReleaseInstance();
Sleep(10);
WaitForMultipleObjects(count,handle_array,TRUE,INFINITE);
for (int j = 0; j < count; ++j)
{
delete opparam_array[j];
}
delete[]opparam_array;
//{{TestDeadLock
// OpParam paramdeadlock(pTestCls,1);
// _beginthread(ThreadSyncClassBase::DeadLockTest,0,¶mdeadlock);
// Sleep(10);
//}}TestDeadLock
pTestCls->ReleaseInstance();
delete []handle_array;
}
void TestThreadSyncMultiplyinstance()
{
int count = 3;
ThreadSyncClassBase **cls_array = new ThreadSyncClassBase*[count];
OpParam **opparam_array = new OpParam *[count*3];
HANDLE *handle_array = new HANDLE[count*3];
for (int i = 0; i < count; ++i)
{
cls_array[i] = new MultiplyInstanceClass;
for (int j = 0; j < 3; ++j)
{
opparam_array[i*3+j] = new OpParam(cls_array[i],j);
handle_array[i*3+j] = HANDLE(_beginthread(ThreadSyncClassBase::OperateFunc,0,reinterpret_cast<void*>(opparam_array[i*3+j])));
Sleep(1234);
}
}
WaitForMultipleObjects(count*3,handle_array,TRUE,INFINITE);
for (int j = 0; j < count*3; ++j)
{
delete opparam_array[j];
}
delete[]opparam_array;
for (int k = 0; k < count; ++k)
{
delete cls_array[k];
}
delete []cls_array;
delete []handle_array;
}
int main()
{
srand(GetTickCount());
TestThreadSyncSingleinstance();
// TestThreadSyncMultiplyinstance();
return 0;
}