Pthread锁定

时间:2011-06-16 04:50:34

标签: c++ pthreads

我已经像这样创建了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()函数,那么其他线程怎么可以进入锁定后面的区域。

我想知道这是否正常。如果你们能看到我需要修理的任何东西,请告诉我。提前谢谢。

1 个答案:

答案 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...