1. 程式人生 > >【linux執行緒】執行緒安全之條件變數

【linux執行緒】執行緒安全之條件變數

條件變數用法:

條件變數一般和互斥量配合,保護執行緒安全或者完成同步資料的功能。

#include <pthread.h>
#define INFINITE 0xFFFFFFFF

#ifndef ETIMEDOUT
#define ETIMEDOUT 10060
#endif

class CWaitObj;

class CWaitObj
{
public:
    explicit CWaitObj(bool manual = false); //explicit 防止一個引數的建構函式進行隱式變化
    
    virtual ~CWaitObj();
    bool    wait(long long msec = INFINITE);
    void    notify();
    void    reset();

protected:
    pthread_mutext_t mutex;
    pthread_cond_t   cond;
    bool signal_flag;
    bool manual_flag;

private:
    CWaitObj(const CWaitObj& src);
    CWaitObj& operator = (const CWaitObj& src);
    void get_abstime_wait(int msec, strut timespec *abstime);
}


CWaitObj::CWaitObj(bool manual)
:manual_flag(manual)
{
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL)
    signal_flag = false;
}

CWaitObj::~CWaitObj()
{
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
}

bool CWait::wait(DWord msec)
{
    pthread_mutex_lock(&mutex);
    int ret = 0;
    if(signal_flag == false)
    {
        if(INFINITE != msec){
            struct timespec nptime;
            get_abstime_wait(msec,&nptime);
            ret = pthread_cond_timedwait(&cond,&mutex,&nptime);
            if(ret && ret != ETIMEDOUT){}
        }
        else{
            ret = pthread_cond_wait(&cond,&mutex);
        }
    }
    if(!manual_flag) signal_flag = false;
    pthread_mutex_unlock(&mutex);

    return (ret == 0)?true:false;
}

void CWaitObj::notify()
{
    pthread_mutex_lock(&mutex);
    signal_flag = true;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
}

void CWaitObj::reset()
{
    pthread_mutex_lock(&mutex);
    signal_flag = false;
    pthread_mutex_unlock(&mutex);
}

void CWaitObj::get_abstime_wait(int msec,struct timespec *abstime)
{
    struct timeval tv;
    long long absmsec;
    gettimeofday(&tv,NULL);
    absmsec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
    absmsec += msec;
   
    abstime->tv_sec = absmsec / 1000;
    abstime->tv_nsec = absmsec % 1000 * 1000000;
}

//定義執行緒函式run
static void* run(void *arg)
{
    CWaitObj* obj = (CWaitObj*)arg;
    while(1)
    {
        cout<<"run start"<<endl;
        obj->wait(2000);//如果不傳引數需要等待notify,否則是等待ms
        cout<<"run end"<<endl;
    }
}

int main()
{
    pthread_t tidp;
    CWaitObj* obj = new CWaitObj();
    cout<<"start to create thread"<<endl;
    if(pthread_create(&tidp,NULL,run,(void*)obj) == -1)
    {
        cout<<"create thread error\r\n"<<endl;
        return -1;
    }
    
    if(pthread_join(tidp,NULL)){
        cout<<"thread is not exit...\r\n";
        return -2;
    }

    return 0;
}