boost :: mutex :: scoped_lock已被使用,它有时会抛出异常

时间:2013-03-13 08:01:53

标签: c++ boost locking mutex boost-thread

我在多线程代码中使用scoped_lock专门访问代码的某些部分,但有时它会抛出异常访问冲突写入位置...

boost::mutex mMutex;    
boost::condition mInputQueueNotEmpty;    
Job* MyThreadPool<Job, JobOutput>::GetNextJob()  
{    
    boost::mutex::scoped_lock lock(mMutex);

    while (mInputQueue.empty())
        mInputQueueNotEmpty.wait(lock);

    // Do something ...
}

我跟踪了代码,发现basic_timed_mutex类中有一个变量active_count,每当发生运行时错误时,该变量都是未初始化的。 运行时错误发生在这里:

bool try_lock()
{
    return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}

我不知道该怎么办!因为我无法访问此变量,我不负责初始化它。

更新

我的功能类是这样的:

#pragma once

#include <vector.h>
#include <boost/thread.hpp>
#include "MyThread.h"
#include <queue>
#include <boost/thread/condition.hpp>

template <class Job, class JobOutput>
class MyThreadPool
{
public:
    MyThreadPool(int processJobWhenArrived);        
    virtual ~MyThreadPool(void);
        void    Initialize(int ThreadsCount);
        void    AddJob(Job* job);
        void    StartProcess();
        Job*    GetNextJob();
    virtual void    FinishJob(Job* job, JobOutput* jobOutput);
        void    WaitUntilAllJobsProcessed();

public:
    vector<MyThread<Job, JobOutput>*> mThreads;

    queue<Job*> mInputQueue;
    queue<pair<Job*,JobOutput*>> mOutputQueue;

    boost::mutex        mMutexAdd;
    boost::mutex        mMutex;
    boost::condition    mInputQueueNotEmpty;
    boost::mutex        mJobOutputMutex;
    boost::mutex        mJobsMutex;
    boost::condition    mProcessJobs;
    bool            mStartProcessJobs;
    int         mJobsInputCount;
    int         mJobsOutputCount;
    int         mPrevJobsOutputCount;
    bool            mProcessJobWhenArrived;
};

template <class Job, class JobOutput>
void MyThreadPool<Job, JobOutput>::Initialize(int threadsCount)
{
    mStartProcessJobs = false;
    for (int t = 0; t < threadsCount; t++)
        mThreads.push_back(new MyThread<Job, JobOutput>(this));
}

template <class Job, class JobOutput>
void MyThreadPool<Job, JobOutput>::AddJob(Job* job)
{
    boost::mutex::scoped_lock lock(mMutexAdd);
    mInputQueue.push(job);
    mJobsInputCount++;

    if (mProcessJobWhenArrived)
        mInputQueueNotEmpty.notify_all();
}

template <class Job, class JobOutput>
Job* MyThreadPool<Job, JobOutput>::GetNextJob()
{
    boost::mutex::scoped_lock lock(mMutex);

    if (mInputQueue.empty() && mStartProcessJobs && mJobsInputCount == mJobsOutputCount)
        mProcessJobs.notify_one();

    while (mInputQueue.empty())
        mInputQueueNotEmpty.wait(lock);

    Job* job = mInputQueue.front();
    mInputQueue.pop();

    return job;
}

这是我使用GetNextJob函数的代码:

#pragma once

#include <MyMemory.h>
#include <boost/thread.hpp>

template <class Job, class JobOutput>
class MyThreadPool;

template <class Job, class JobOutput>
class MyThread
{           
public:
    static void StaticRun(MyThread* p);
    void Run();

public:
    boost::thread   mThread;            
    MyThreadPool<Job, JobOutput>*   mThreadPool;            
};

#include "MyThreadPool.h"
template <class Job, class JobOutput>
MyThread<Job, JobOutput>::MyThread(MyThreadPool<Job, JobOutput>* threadPool)
{
    mThread = boost::thread(StaticRun, this);
    mThreadPool = threadPool;
}

template <class Job, class JobOutput>
void MyThread<Job, JobOutput>::StaticRun(MyThread* p)
{
    p->Run(); 
}

template <class Job, class JobOutput>
void MyThread<Job, JobOutput>::Run()
{
    JobOutput   *jobOutput;
    while (true)
    {
        Job* job = mThreadPool->GetNextJob();
        jobOutput = Process (job);
        mThreadPool->FinishJob(job, jobOutput);
    }

}

有一个类可以吸引MyThreadPool

class SsThreadPool : public MyThreadPool<Job, JobOutput>

这就是使用threadPool的地方:

class BPS
{
    //...
    SsThreadPool            mJobsThreadPool;
    //...
}
void    BPS::Initialize()
{
    mJobsThreadPool.Initialize(mConcurrentThreadsCount);
}

void    BPS::f()
{
    //...
    for (int i = 0; i < jobsCount; i++)
    {
        //...
        mJobsThreadPool.AddJob(job);
        //...

    }
    mJobsThreadPool.StartProcess(); 
    mJobsThreadPool.WaitUntilAllJobsProcessed();
    //...
}

2 个答案:

答案 0 :(得分:2)

它会引发访问冲突,因为您尝试锁定已销毁的mutex。由于互斥锁是您的类的成员,这意味着您的代码尝试访问被破坏实例的成员函数(“悬空指针”)。要调试这种情况,请在~MyThreadPool中放置一个断点,并查看它何时被调用。

答案 1 :(得分:0)

也许持有互斥锁的对象被破坏,然后有人试图访问互斥锁。你的代码可以吗?