天天看點

在linux下實作CSingleLock函數

最近做的項目涉及到多線程處理的問題,因為考慮到在windows下實作的效率,在裡面是有了CSingleLock,現在需要将項目擴充到可以跨平台。是以就面臨兩個選擇,第一就是将所有涉及到作業系統平台的地方都使用第三方的庫來替換,優點是省事,缺點是之前針對windows做的一些優化就白費了;第二個就是對windows的相關函數小修改甚至不修改,然後增加linux平台下的函數,此種方式優點是保持之前windows下優化的部分,缺點就是自己寫相應的函數比較費時,而且需要測試。經過評估項目本身的特性,覺得還是第二種方式要适合一點。本文就給出CSingleLock的實作源碼和簡單測試程式。

閑話少說,先貼上代碼

#ifndef TMUTEX_H
#define TMUTEX_H

#include <pthread.h>
#include <stdio.h>

class CThreadMutex
{
public:
    CThreadMutex()
    {
        pthread_mutex_init(&mtx, NULL);
    }
    
    ~CThreadMutex()
    {
        printf("release 1===================== \n");
        pthread_mutex_destroy(&mtx);
    }
    
    inline void lock()
    {
        pthread_mutex_lock(&mtx);
    }    

    inline void unlock()
    {
        printf("unlock 1===================== \n");
        pthread_mutex_unlock(&mtx);
    }

private:
    pthread_mutex_t mtx;
};


//class NullMutex
//{
//public:
//    inline void lock()  {};
//    inline void unlock(){};
//};

class CSingleLock
{
public:
    CSingleLock(CThreadMutex &mtx) : m_mtx(mtx) , m_bIsLocked(false)
    {}
    
    void Lock()
    {
        m_bIsLocked = true;
        m_mtx.lock();
        printf("lock ++++++ \n");
    }

    void UnLock()
    {
        if (m_bIsLocked)
        {
            printf("++++++++++++++++++++++++++++ \n");
            m_bIsLocked = false;
            m_mtx.unlock();
            printf("Unlock ++++++ \n");
        }
    }

    ~CSingleLock()
    {
        printf("release 2===================== \n");
        m_mtx.unlock();
    }

protected:
    bool m_bIsLocked;
    CThreadMutex &m_mtx;

};

#endif      

實作的基本思路就是對posix标準中的互斥鎖封裝成類

CThreadMutex,然後通過類CSingleLock進行調用。

測試程式如下:

#include <stdio.h>
#include <pthread.h>
#include "CSingleLock.h"
#include <unistd.h>

typedef CThreadMutex MUTEX_TYPE;
//typedef NullMutex MUTEX_TYPE;

MUTEX_TYPE g_mtx;

int a = 200;
int b = 100;

void *add(void *pPM)
{
    {
    CSingleLock gd(g_mtx);
    gd.Lock();
    
    a -= 50;
    
    sleep(15);

    b += 50;    
    
    printf("leave ==================== \n");      
//gd.Unlock();  //顯式的調用釋放鎖函數

    }
    
    printf("in sleep\n"); 
    sleep(20);
}


void *sub(void *pPM)
{
    sleep(2);
    CSingleLock gd(g_mtx);
    gd.Lock();
    printf("%d\n", a+b);      
//gd.Unlock();   //顯式的調用釋放鎖函數</span>
}

int main(int argc, char **argv)
{
    pthread_t tid1, tid2;
    //pthread_t tid3, tid4;

    pthread_create(&tid1, NULL, add, NULL);
    pthread_create(&tid2, NULL, sub, NULL);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    return 0;  
}      

          線程tid1和tid2都需要擷取鎖g_mtx,線上程tid1中,在函數包含的花括号中,擷取該鎖,在離開該花括号時,應該自動釋放該鎖(也就是說,在列印leave後就應該釋放該鎖),這時tid1開始sleep,tid2擷取到該鎖。當tid2結束後也自動釋放該鎖。當然上述鎖的釋放也可以顯式的調用Unlock函數來釋放。測試程式結果如下:(家裡的ubuntu在更新,明日補上程式結果截圖)

繼續閱讀