简体   繁体   English

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

[英]boost::mutex::scoped_lock has been used and It sometimes throws the exception

I am using scoped_lock in my multithread code to exclusively access to some part of code, but sometimes it throws to the exception Access violation writing location ... . 我在我的多线程代码中使用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 ...
}

I traced the code and I found out that there is a variable active_count in basic_timed_mutex class and whenever the runtime error happens, this variable is uninitialized. 我跟踪了代码,发现在basic_timed_mutex类中有一个变量active_count,并且每当发生运行时错误时,该变量都将被初始化。 runtime error happens around here: 运行时错误发生在这里:

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

I do not know what should I do! 我不知道该怎么办! because I do not have access to this variable and I am not responsible for initializing it. 因为我无权访问此变量,因此不负责初始化它。

UPDATE 更新

the class of my function is this: 我函数的类是这样的:

#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;
}

and this is the code where I use GetNextJob function: 这是我使用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);
    }

}

there is a class that inhrerits MyThreadPool 有一个类会激怒MyThreadPool

class SsThreadPool : public MyThreadPool<Job, JobOutput>

and this is where threadPool has been used: 这是使用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();
    //...
}

It raises access violation, because you attempt to lock a destroyed mutex . 因为您尝试锁定损坏的mutex锁,所以会引起访问冲突。 Since the mutex is a member of your class, it means your code attempts to access a member-function of a destroyed instance ("dangling pointer"). 由于互斥锁是您的类的成员,所以这意味着您的代码尝试访问已破坏实例的成员函数(“悬挂指针”)。 To debug this case, put a breakpoint in ~MyThreadPool and see when it gets called. 要调试这种情况,请在~MyThreadPool放置一个断点,看看何时调用它。

Maybe the object,that is holding the mutex, gets destroyed and then someone is trying to access the mutex. 可能是持有互斥锁的对象被破坏,然后有人试图访问该互斥锁。 possible in your code ? 您的代码中可能吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM