多线程,锁

现在公司的代码动不动各种崩溃,原因大部分是由不加锁引起的。

例如很多的底层数据,全部封装成了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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值