2013-03-13 3 views
6

Я использую scoped_lock в моем многопоточном коде исключительно доступ к некоторой части коды, но иногда он бросает на исключение доступа место нарушения пишущего ....повышения :: мьютекс :: 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 ... 
} 

Я проследил код, и я узнал, что есть переменная active_count в классе basic_timed_mutex и всякий раз, когда происходит ошибка времени выполнения, эта переменная не инициализирована. ошибка во время выполнения происходит здесь:

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

Я не знаю, что я должен делать! потому что у меня нет доступа к этой переменной, и я не несу ответственность за ее инициализацию.

UPDATE

класс моей функции заключается в следующем:

#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(); 
    //... 
} 
+1

Это фактический код, для которого вы получаете нарушение доступа? –

+0

является 'mMutex' глобальной переменной? Вы пытаетесь получить к нему доступ из конструктора другого глобального объекта? – 2013-03-13 08:21:39

+1

Да, я получаю исключение в этой строке: 'boost :: mutex :: scoped_lock lock (mMutex);' –

ответ

0

Может быть, объект, который держит мьютекс, разрушается, а затем кто-то пытается получить доступ к семафор. возможно в вашем коде?

+0

Я так не думаю. время жизни этого объекта равно целям программы. –

+0

Вы в главной роли? – rioki

2

Это вызывает нарушение прав доступа, поскольку вы пытаетесь заблокировать уничтоженный mutex. Поскольку мьютекс является членом вашего класса, это означает, что ваш код пытается получить доступ к функции-члену уничтоженного экземпляра («оборванный указатель»). Чтобы отладить этот случай, поместите контрольную точку в ~MyThreadPool и посмотрите, когда она будет вызвана.

+0

Как вы сказали, я поставил точку останова в '~ MyThreadPool', но перед вызовом деструктора возникает нарушение прав доступа. –

+0

@ Самане Саадат Ок, я вижу. Другой вариант (намного хуже) - это кучное повреждение, которое «перезаписывает» часть «mMutex».Во всяком случае, что-то разрушает объект мьютекса. Кстати, какую версию вы используете? –

+0

Я использую boost 1.47.0 для немедленной обработки ошибки, которую я определил 'mMutex' в методе' GetNextJob', после того, как это нарушение прав доступа к модификации поднимается рядом с следующей строкой, и теперь у него есть проблема с 'mInputQueue'. –

Смежные вопросы