保护原语
为了确保一致性,多线程程序必须在共享数据周围使用保护原语。
Protection Primitives in ACE
Primitive
Description
ACE_Mutex |
Wrapper class around the mutual-exclusion mechanism and used to provide a simple, efficient mechanism to serialize access to a shared resource. Similar in functionality to a binary sempahore. Can be used for mutual exclusion among both threads and processes. |
ACE_Thread_Mutex |
Can be used in place of ACE_Mutex and is specific for synchronization of threads. |
ACE_Recursive_Thread_Mutex |
Mutex that is recursive, that is, can be acquired multiple times by the same thread. Note that to work correctly, it must be released as many times as it was acquired. |
ACE_RW_Mutex |
Wrapper class that encapsulates readers/writer locks. These locks are acquired differently for reading and writing, thus enabling multiple readers to read while no one is writing. These locks are nonrecursive. |
ACE_RW_Thread_Mutex |
Can be used in place of ACE_RW_Mutex and is specific for synchronization of threads. |
ACE_Token |
Tokens are the richest and heaviest locking primitive available in ACE. The locks are recursive and allow for read and write locking. Also, strict FIFO ordering of acquisition is enforced; all threads that call acquire() enter a FIFO queue and acquire the lock in order. |
ACE_Atomic_Op |
Template wrapper that allows for safe arithmetic operations on the specified type. |
ACE_Guard |
Template-based guard class that takes the lock type as a template parameter. |
ACE_Read_Guard |
Guard that uses acquire_read() on a read/write guard during construction. |
ACE_Write_Guard |
Guard that uses acquire_write() on a read/write guard during construction. |
#include <ace/Atomic_Op_T.h> #include <ace/Thread_Mutex.h> #include <ace/Log_Msg.h> #include <ace/Task.h> typedef ACE_Atomic_Op<ACE_Thread_Mutex, unsigned int> SafeUInt; typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> SafeInt; static const int Q_SIZE = 100; //缓冲区大小 static const int MAX_PROD = 1000; //最大生产数 class Consumer : public ACE_Task_Base { private: int* buf_; SafeUInt& in_; SafeUInt& out_; public: Consumer(int *buf, SafeUInt &in, SafeUInt& out) : buf_(buf), in_(in), out_(out) { } int svc(void) { while (1) { int item; // Busy wait. do { } while (in_.value() - out_.value() == 0); item = buf_[out_.value() % Q_SIZE]; out_++; ACE_DEBUG((LM_DEBUG, ACE_TEXT("Consumed %d\n"), item)); if (check_termination(item)) break; } return 0; } int check_termination(int item) { return (item == MAX_PROD); } }; class Producer : public ACE_Task_Base { private: int* buf_; SafeUInt& in_; SafeUInt& out_; public: Producer(int* buf, SafeUInt& in, SafeUInt& out) : buf_(buf), in_(in), out_(out) { } int svc(void) { SafeInt itemNo = 0; while (1) { // Busy wait. do { } while(in_.value() - out_.value() == Q_SIZE); itemNo++; buf_[in_.value() % Q_SIZE] = itemNo.value(); in_++; ACE_DEBUG((LM_DEBUG, ACE_TEXT("Produced %d \n"), itemNo.value())); if (check_termination(itemNo.value())) break; } return 0; } int check_termination(int item) { return (item == MAX_PROD); } }; int ACE_TMAIN (int, ACE_TCHAR *[]) { int shared_buf[Q_SIZE]; SafeUInt in = 0; SafeUInt out = 0; Producer producer(shared_buf, in, out); Consumer consumer(shared_buf, in, out); producer.activate(); consumer.activate(); producer.wait(); consumer.wait(); return 0; }
Primitive
Description
ACE_Condition |
A condition variable; allows signaling other threads to indicate event occurrence |
ACE_Semaphore |
A counting semaphore; can be used as a signaling mechanism and also for synchronization purposes |
ACE_Barrier |
Blocks all threads of execution until they all reach the barrier line, after which all threads continue |
ACE_Event |
A simple synchronization object that is used to signal events to other threads |
#include <ace/Log_Msg.h> #include <ace/Task.h> #include <ace/Semaphore.h> #include <ace/Message_Block.h> class Consumer : public ACE_Task<ACE_MT_SYNCH> { private: ACE_Semaphore& psema_; ACE_Semaphore& csema_; int exit_condition_; public: enum { N_THREADS = 5 }; Consumer(ACE_Semaphore& psema, ACE_Semaphore& csema) : psema_(psema), csema_(csema), exit_condition_(0) { } int svc(void) { while(!is_closed()) consume_item(); return 0; } void consume_item() { csema_.acquire(); if (!is_closed()) { ACE_Message_Block *mb; this->getq(mb); if (mb->msg_type() == ACE_Message_Block::MB_HANGUP) { //挂断消息 shutdown(); mb->release(); return; } else { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) Consumed %d\n"), *((int*)mb->rd_ptr()))); mb->release(); } //psema_值增一,允许生产者继续执行 psema_.release(); } } void shutdown(void) { exit_condition_ = 1; //唤醒消息队列上的所有线程 this->msg_queue()->deactivate(); //释放在信号量上等待的所有线程 csema_.release(N_THREADS); } int is_closed(void) { return exit_condition_; } }; class Producer : public ACE_Task_Base { public: enum { MAX_PROD = 128 }; Producer(ACE_Semaphore& psema, ACE_Semaphore& csema, Consumer &consumer) : psema_(psema), csema_(csema), consumer_(consumer) { } int svc(void) { for (int i = 0; i <= MAX_PROD; i++) produce_item(i); hang_up(); return 0; } void produce_item(int item) { psema_.acquire(); ACE_Message_Block *mb = new ACE_Message_Block(sizeof(int), ACE_Message_Block::MB_DATA); ACE_OS::memcpy(mb->wr_ptr(), &item, sizeof item); mb->wr_ptr(sizeof(int)); this->consumer_.putq(mb); ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) Produced %d\n"), item)); //生产出一个新元素,csema_值增一 csema_.release(); } void hang_up() { psema_.acquire(); ACE_Message_Block *mb = new ACE_Message_Block(0, ACE_Message_Block::MB_HANGUP); this->consumer_.putq(mb); csema_.release(); } private: ACE_Semaphore& psema_; ACE_Semaphore& csema_; Consumer& consumer_; }; int ACE_TMAIN(int, ACE_TCHAR *[]) { ACE_Semaphore psem(5); //队列中能容纳的最大数目为5 ACE_Semaphore csem(0); //在csem的release()之前,消费者完全不能进行消费 Consumer consumer(psem, csem); Producer producer(psem, csem, consumer); producer.activate(); //多个消费者线程 consumer.activate(THR_NEW_LWP | THR_JOINABLE, Consumer::N_THREADS); producer.wait(); consumer.wait(); return 0; }
#include <ace/OS.h> #include <ace/Log_Msg.h> #include <ace/Task.h> #include <ace/Barrier.h> class HA_CommandHandler : public ACE_Task<ACE_MT_SYNCH> { private: ACE_Barrier& startup_barrier_; ACE_Barrier& shutdown_barrier_; public: enum { N_THREADS = 5 }; HA_CommandHandler(ACE_Barrier& startup_barrier, ACE_Barrier& shutdown_barrier) : startup_barrier_(startup_barrier), shutdown_barrier_(shutdown_barrier) { } //随机初始化时间 void initialize_handler(void) { ACE_OS::sleep(ACE_OS::rand() % 10); } //随机执行时间 int handle_command_requests(void) { ACE_OS::sleep(ACE_OS::rand() % 10); return -1; } int svc(void) { initialize_handler(); startup_barrier_.wait(); ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t: %D) Started\n"))); while(handle_command_requests() > 0) ; shutdown_barrier_.wait(); ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t: %D) Ended\n"))); return 0; } }; int ACE_TMAIN(int, ACE_TCHAR *[]) { ACE_Barrier startup_barrier(HA_CommandHandler::N_THREADS); ACE_Barrier shutdown_barrier(HA_CommandHandler::N_THREADS); HA_CommandHandler handler(startup_barrier, shutdown_barrier); handler.activate(THR_NEW_LWP | THR_JOINABLE, HA_CommandHandler::N_THREADS); handler.wait(); return 0; }
class ClientContext { public: void *get_attribute(const char *name); void set_attribute(const char *name, void *value); private: Map attributeMap_; }; class HA_CommandHandler : public ACE_Task<ACE_MT_SYNCH> { private: ACE_TSS<ClientContext> tss_ctx_; public: virtual int svc(void) { //... this->tss_ctx_->get_attribute("attribute1"); return 0; } };