監視器對象設計模式使併發方法的執行同步化,以確保任一時刻僅有一個方法在對象內運行。別名線程安全被動對象。
問題場景:應用程序包含被多個線程併發調用的對象。這些方法通常修改其對象的內部狀態。爲了併發線程內正確執行,有必要對對象的訪問進行同步和調度。如果客戶機必須顯示的獲取和釋放底層同步機制,如信號、互斥或條件變量。那麼併發應用程序更難編程。因此,對象應該負責確保它們需要同步的任何方法被透明的串行化。
代碼示例:
#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;
}