P螺纹锁定

Pthread locking

本文关键字:锁定      更新时间:2023-10-16

我创建了类似的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_ */

MutexCondation.cpp文件

#include "MutexCondition.h"
bool MutexCondition::init(){
    printf("MutexCondition::init calledn");
    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;
}

我创建了一个WorkHandler,它扩展了Mutex Condition

#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 calledn");
    WorkHandler *ptr = reinterpret_cast<WorkHandler*>(delegate);
    ptr->workLoop();
    return NULL;
}
void WorkHandler::workLoop(){
    printf("WorkHandler::workLoop calledn");
    //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 lockingn", pthread_self());
    lock();
    printf("WorkHandler::insertWork Locked and inserting int queue n");
    m_workQueue.push(w);
    signal();
    unLock();
}
Work* WorkHandler::getWork(){
    printf("WorkHandler::getWork lockingn");
    lock();
    printf("WorkHandler::getWork lockedn");
    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 jobn");
    m_workQueue.pop();
    unLock();
    return work;
}

问题是我已经锁定了getWork()函数中的互斥变量,就像这个

    printf("WorkHandler::getWork lockingn");
    lock();
    printf("WorkHandler::getWork lockedn");

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

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

原因是当线程等待条件变量时,互斥锁被解锁。

这是预期的行为。

当条件变量发出信号时,线程不会被释放以运行,直到重新获取锁为止。

如果您将功能更改为:

Work* WorkHandler::getWork(){
          // Remoed this as it is non-determinstic when it will be printed.
    lock();
    printf("WorkHandler::getWork lockedn");
    while(m_workQueue.empty()){//Need while instead of If
        printf("WorkHandler::getWork waiting...n");
        wait();
        printf("WorkHandler::getWork waiting DONEn");    // Added this.
    }
    Work *work = m_workQueue.front();
    printf("WorkHandler::getWork got a jobn");
    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...