代码改变世界

C++多线程环境下注意共享资源的释放顺序

2013-11-16 21:45  DVwei  阅读(1127)  评论(0编辑  收藏  举报

  比如我现在写一个多线程下载程序,包含DownloadTask、HttpDownload两个类。

class DownloadTask
{
     //省略n行代码
public:
int m_threads;//需创建的线程总数 CCriticalSection m_cs;
//临界区
void Stop(); }; class HttpDownload { //省略n行代码
HttpDownload(DownloadTask* task): m_task(task) { } public:
DownloadTask* m_task;
void Start();//开始下载 }

  每一个HttpDownload对象都是一个线程的执行单元,同一个任务下的所有线程共享同一个DownloadTask对象中的所有资源。如果这样编写下载程序:

//在某一个函数中
{
    DownloadTask* myTask =  new DownloadTask()
    HttpDownload* download = new HttpDownload(myTask);
    for(int i = 0; i < myTask->m_threads; ++i)
        AfxBeginThread(downloadThreadFun, download);
    return 0;
}

UINT downloadThreadFun(LPVOID lParam)
{
    auto_ptr<HttpDownload> pDownload((HttpDownload*)lParam);
    pDownload->Start();
    return 0;
}

void SetStop(DownloadTask* task)
{
task->Stop();
delete task;
}

  在某一时刻,比如用户点击停止下载时,我们就需要delete掉这个DownloadTask对象。但是如果当前还有线程在运行,这样delete掉就会影响这些线程,直接导致程序出错。

  所以,必须在delete DownloadTask对象前确定此下载任务中所有线程已经停止。于是可以这样写:

class DownloadTask
{
     //省略n行代码
public:
    int m_threads;//需要创建的线程总数
    CCriticalSection m_cs;//临界区
    int m_currentThreads;//当前运行的线程数
    void Stop();
};

UINT downloadThreadFun(LPVOID lParam)
{
      auto_ptr<HttpDownload> pDownload((HttpDownload*)lParam);
      CSingleLock singleLock(&pDownload->m_task->m_cs);
      pDownload->Start();
      singleLock.Lock()
      --pDownload->m_task->m_currentThreads;
      return 0;
}

void SetStop(DownloadTask* task)
{
     CSingleLock singleLock(&task->m_cs);
     task->Stop();
     singleLock.Lock();
     if(task->m_currentThreads == 0)
        delete task;
     return 0;
}

  这样就保证在所有线程已经结束时才delete掉这个任务的DownloadTask对象。