Pthread锁定

use*_*799 4 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_ */
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

我创建了一个扩展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_ */
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

问题是我已经在这样的getWork()函数中锁定了互斥变量

    printf("WorkHandler::getWork locking\n");
    lock();
    printf("WorkHandler::getWork locked\n");
Run Code Online (Sandbox Code Playgroud)

但是,如果我看到日志语句,那么所有线程打印这两个日志语句,我认为这是一个问题.我没有把任何东西放入队列,所以第一个线程应该等待条件变量发出信号并且它正常工作.但是,如果第一个线程被锁定并且没有调用unlock()函数,那么其他线程怎么可以进入锁定后面的区域.

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

Mar*_*ork 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;
}
Run Code Online (Sandbox Code Playgroud)

如果您随后创建了三个线程,我期望:

WorkHandler::getWork locked
WorkHandler::getWork waiting...
WorkHandler::getWork locked;
WorkHandler::getWork waiting...
WorkHandler::getWork locked
WorkHandler::getWork waiting...
Run Code Online (Sandbox Code Playgroud)

对于每个信号呼叫,我希望:

WorkHandler::Thread %d insertWork locking
WorkHandler::insertWork Locked and inserting int queue
WorkHandler::getWork waiting DONE
WorkHandler::getWork got a job
Run Code Online (Sandbox Code Playgroud)

无论你多快地调用信号,我总是希望看到这两个按顺序打印.
因为在重新获取锁之前,线程不会从条件变量中释放.

注意你可能会看到.

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...
Run Code Online (Sandbox Code Playgroud)