我已经像这样创建了MutexCondition类
/*MutexCondtion.h file*/
#ifndef MUTEXCONDITION_H_
#define MUTEXCONDITION_H_
#include <pthread.h>
#include <stdio.h>
class MutexCondition {
private:
bool init();
bool destroy();
protected:
pthread_mutex_t m_mut;
pthread_cond_t m_con;
public:
MutexCondition(){
init();
}
virtual ~MutexCondition(){
destroy();
}
bool lock();
bool unLock();
bool wait();
bool signal();
};
#endif /* MUTEXCONDITION_H_ */
MutexCondtion.cpp文件
#include "MutexCondition.h"
bool MutexCondition::init(){
printf("MutexCondition::init called\n");
pthread_mutex_init(&m_mut, NULL);
pthread_cond_init(&m_con, NULL);
return true;
}
bool MutexCondition::destroy(){
pthread_mutex_destroy(&m_mut);
pthread_cond_destroy(&m_con);
return true;
}
bool MutexCondition::lock(){
pthread_mutex_lock(&m_mut);
return true;
}
bool MutexCondition::unLock(){
pthread_mutex_unlock(&m_mut);
return true;
}
bool MutexCondition::wait(){
pthread_cond_wait(&m_con, &m_mut);
return true;
}
bool MutexCondition::signal(){
pthread_cond_signal(&m_con);
return true;
}
我创建了一个扩展MutexCondition
的WorkHandler#ifndef WORKHANDLER_H_
#define WORKHANDLER_H_
#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include <pthread.h>
#include <stdio.h>
#include <list>
#include "MutexCondition.h"
#include "Work.h"
using namespace::std;
class WorkHandler: MutexCondition {
private:
int m_maxThreads;
queue<Work*> m_workQueue;
list<pthread_t*> m_workThreadList; //Just thread IDs
pthread_t **m_workThreads;
void workLoop();
bool initThreads();
void insertWork(Work *work);
Work* getWork();
protected:
static void* runWorkThread(void* delegate);
public:
WorkHandler(int maxThreads);
virtual ~WorkHandler();
};
#endif /* WORKHANDLER_H_ */
WorkHandler.cpp文件
#include "WorkHandler.h"
WorkHandler::WorkHandler(int maxThreads) {
// TODO Auto-generated constructor stub
m_maxThreads = maxThreads;
initThreads();
}
WorkHandler::~WorkHandler() {
// TODO Auto-generated destructor stub
}
void* WorkHandler::runWorkThread(void *delegate){
printf("WorkHandler::runWorkThread called\n");
WorkHandler *ptr = reinterpret_cast<WorkHandler*>(delegate);
ptr->workLoop();
return NULL;
}
void WorkHandler::workLoop(){
printf("WorkHandler::workLoop called\n");
//WorkHandler *ptr = reinterpret_cast<WorkHandler*>(delegate);
while(1){
Work *work = getWork();
}
}
bool WorkHandler::initThreads(){
for(int i=0; i < m_maxThreads; i++){
pthread_t *thread(new pthread_t);
m_workThreadList.push_back(thread);
if(pthread_create(thread, NULL, runWorkThread, reinterpret_cast<void *>(this))!=0){
perror("InitThreads, pthread_create error \n");
return false;
}
pthread_detach(*thread);
}
return true;
}
void WorkHandler::insertWork(Work* w){
printf("WorkHandler::Thread %d insertWork locking\n", pthread_self());
lock();
printf("WorkHandler::insertWork Locked and inserting int queue \n");
m_workQueue.push(w);
signal();
unLock();
}
Work* WorkHandler::getWork(){
printf("WorkHandler::getWork locking\n");
lock();
printf("WorkHandler::getWork locked\n");
while(m_workQueue.empty()){//Need while instead of If
printf("WorkHandler::getWork waiting...\n");
wait();
}
Work *work = m_workQueue.front();
printf("WorkHandler::getWork got a job\n");
m_workQueue.pop();
unLock();
return work;
}
问题是我已将锁定互斥变量锁定在getWork()函数中,如此
printf("WorkHandler::getWork locking\n");
lock();
printf("WorkHandler::getWork locked\n");
但是,如果我看到日志语句,那么所有线程都打印了这两个日志语句,我认为这是一个问题。我没有把任何东西放入队列,所以第一个线程应该等待条件变量发出信号并且它正常工作。但是,如果第一个线程被锁定并且没有调用unlock()函数,那么其他线程怎么可以进入锁定后面的区域。
我想知道这是否正常。如果你们能看到我需要修理的任何东西,请告诉我。提前谢谢。
答案 0 :(得分:7)
原因是当线程等待条件变量时,互斥锁被解锁。
这是预期的行为。
当发出条件变量信号时,在重新获取锁之前,线程不会被释放。
如果将功能更改为:
Work* WorkHandler::getWork(){
// Remoed this as it is non-determinstic when it will be printed.
lock();
printf("WorkHandler::getWork locked\n");
while(m_workQueue.empty()){//Need while instead of If
printf("WorkHandler::getWork waiting...\n");
wait();
printf("WorkHandler::getWork waiting DONE\n"); // Added this.
}
Work *work = m_workQueue.front();
printf("WorkHandler::getWork got a job\n");
m_workQueue.pop();
unLock();
return work;
}
如果你创建了三个我想要的线程:
WorkHandler::getWork locked
WorkHandler::getWork waiting...
WorkHandler::getWork locked;
WorkHandler::getWork waiting...
WorkHandler::getWork locked
WorkHandler::getWork waiting...
对于每次信号呼叫,我都希望:
WorkHandler::Thread %d insertWork locking
WorkHandler::insertWork Locked and inserting int queue
WorkHandler::getWork waiting DONE
WorkHandler::getWork got a job
无论你多快地拨打信号,我总是希望看到这两个按顺序打印 因为在重新获取锁之前,线程不会从条件变量中释放。
请注意,您可能会看到。
WorkHandler::Thread %d insertWork locking
WorkHandler::insertWork Locked and inserting int queue
WorkHandler::getWork locked // A previously released thread finishes and steals
// the job before the signalled thread can aquire the lock.
WorkHandler::getWork got a job
WorkHandler::getWork waiting DONE // Now the released thread just goes back to waiting.
WorkHandler::getWork waiting...