設計模式C++實現:監視器對象

監視器對象設計模式使併發方法的執行同步化,以確保任一時刻僅有一個方法在對象內運行。別名線程安全被動對象。

問題場景:應用程序包含被多個線程併發調用的對象。這些方法通常修改其對象的內部狀態。爲了併發線程內正確執行,有必要對對象的訪問進行同步和調度。如果客戶機必須顯示的獲取和釋放底層同步機制,如信號、互斥或條件變量。那麼併發應用程序更難編程。因此,對象應該負責確保它們需要同步的任何方法被透明的串行化。
代碼示例:

#include <iostream>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <pthread.h>
using namespace std;
class Mutex
{
public:
    Mutex()
    {
        pthread_mutex_init(&_lock, NULL);
    }
    virtual ~Mutex()
    {
        pthread_mutex_destroy(&_lock);
    }
    void Lock()
    {
        pthread_mutex_lock(&_lock);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&_lock);
    }
    pthread_mutex_t* GetLock()
    {
        return &_lock;
    }

private:
    pthread_mutex_t _lock;

};
class TreadCond
{
public:
    TreadCond()
    {
        pthread_cond_init(&m_cond, NULL);
    }
    virtual ~TreadCond()
    {
        pthread_cond_destroy(&m_cond);
    }
    void CondNotify()
    {
        pthread_cond_signal(&m_cond);
    }
    void CondWait(pthread_mutex_t* lock)
    {
        pthread_cond_wait(&m_cond, lock);
    }

private:
    pthread_cond_t m_cond;
};

class ScopedLock
{
public:
    ScopedLock( Mutex& mutex_obj ) : _mutex_obj(mutex_obj)
    {
        _mutex_obj.Lock();
    }
    ~ScopedLock()
    {
        _mutex_obj.Unlock();
    }
private:
    Mutex& _mutex_obj;

};
class MessageQueue
{
    enum {MAX_SIZE = 100,};
public:
    MessageQueue(int size = MAX_SIZE):
        m_size(size),
        m_mesageCount(0)

    {

    }
    ~MessageQueue()
    {
        delete m_array;
    }

    void put(int value)
    {
        ScopedLock lock(m_mutex);
        while(i_full())
        {
           m_notFullCond.CondWait(m_mutex.GetLock());
           cout<<"full"<<endl;
        }
        i_put(value);
        //cout<<"put:"<<value<<endl;
        m_notEmptyCond.CondNotify();
    }
    int get()
    {
        ScopedLock lock(m_mutex);
        while(i_empt())
        {
            m_notEmptyCond.CondWait(m_mutex.GetLock());
            cout<<"empt"<<endl;
        }
        int value = i_get();
        //cout<<"get:"<<value<<endl;
        m_notFullCond.CondNotify();
        return value;
    }
    bool empt()
    {
        ScopedLock lock(m_mutex);
        return i_empt();
    }
    bool full()
    {
        ScopedLock lock(m_mutex);
        return i_full();
    }
private:
    bool i_empt()
    {
        return m_mesageCount == 0;
    }
    bool i_full()
    {
        return m_mesageCount == m_size;
    }
    void i_put(int value)
    {
        m_array[m_mesageCount] = value;
        m_mesageCount++;
        //cout<<"putmsgcout:"<<m_mesageCount<<endl;
    }
    int i_get()
    {
        int val = m_array[m_mesageCount-1];;
        m_mesageCount--;
        //cout<<"getmsgcout:"<<m_mesageCount<<endl;
        return val;
    }
private:
    int m_size;
    int m_array[MAX_SIZE];
    int m_mesageCount;
    Mutex m_mutex;
    TreadCond m_notEmptyCond;
    TreadCond m_notFullCond;
};
MessageQueue g_queue;
void *pthr_fun1(void *arg)
{
    int i = 1;
    while(i < 30000)
    {
        g_queue.put(i);
        cout<<"thread1_put:"<<i<<endl;
        i++;
    }
}
void *pthr_fun2(void *arg)
{
    int i = 0;
    int value = 0;
    while(i < 10000)
    {
        value = g_queue.get();
        cout<<"thread2_get:"<<value<<endl;
        i++;
    }
}
void *pthr_fun3(void *arg)
{
    int i = 0;
    int value = 0;
    while(i < 10000)
    {
        value = g_queue.get();
        cout<<"thread3_get:"<<value<<endl;
        i++;
    }
}
void *pthr_fun4(void *arg)
{
    int i = 0;
    int value = 0;
    while(i < 10000)
    {
        value = g_queue.get();
        cout<<"thread4_get:"<<value<<endl;
        i++;
    }
}
int main () {
    pthread_t thread1, thread2, thread3, thread4;
    pthread_create(&thread1,NULL,pthr_fun1,NULL);\
    pthread_create(&thread2,NULL,pthr_fun2,NULL);\
    pthread_create(&thread3,NULL,pthr_fun3,NULL);\
    pthread_create(&thread4,NULL,pthr_fun4,NULL);\

    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);
    pthread_join(thread3,NULL);
    pthread_join(thread4,NULL);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章