ACE_linux:条件变量( Producers and Consumers ):单-单
1.涉及类
ACE_Thread_Mutex //ACE读写锁
ACE_Condition //ACE条件变量
ACE_Guard //ACE加锁
ACE_Thread_Manager //ACE线程管理
2.简介
ACE读/写锁
如果线程正在等待某个特定条件发生,它应该如何处理这种情况?它可以重复对互斥对象锁定和解锁,每次都会检查共享数据结构,以查找某个值。但这是在浪费时间和资源,而且这种繁忙查询的效率非常低。解决这个问题的最佳方法是使用ACE_Condition调用来等待特殊条件发生。
3.示例代码
1 #include <iostream> 2 #include "ace/Thread_Manager.h" 3 #include "ace/Guard_T.h" 4 #include "ace/OS_NS_time.h" 5 //生产朱和消费者( Producers and Consumers ):单-单(单-多,多-单,多-多) 6 using namespace std; 7 ACE_Thread_Mutex mutex; 8 ACE_Condition<ACE_Thread_Mutex > cond(mutex); 9 10 ACE_THR_FUNC_RETURN ThreadFunProducers(void *arg) 11 { 12 ACE_OS::sleep(1); 13 ACE_thread_t threadId=ACE_Thread_Manager::instance()->thr_self(); 14 15 ACE_Guard<ACE_Thread_Mutex > guard(mutex); 16 cout<<"Thread ProducersLock begin NO:"<<threadId<<endl; 17 18 cout<<"Thread ProducersLock end NO:"<<threadId<<endl; 19 cond.signal(); 20 return NULL; 21 } 22 ACE_THR_FUNC_RETURN ThreadFunConsumers(void *arg) 23 { 24 ACE_thread_t threadId=ACE_Thread_Manager::instance()->thr_self(); 25 26 ACE_Guard<ACE_Thread_Mutex > guard(mutex); 27 cond.wait(); 28 cout<<"Thread ConsumersLock begin NO:"<<threadId<<endl; 29 30 cout<<"Thread ConsumersLock end NO:"<<threadId<<endl; 31 return NULL; 32 } 33 34 int main(int argc, char *argv[]) 35 { 36 //1000纳秒=1ms 37 timespec_t t; 38 t.tv_sec=0;t.tv_nsec=1000; 39 40 ACE_Thread_Manager* pThrMgr = ACE_Thread_Manager::instance(); 41 //依次一读一写依次3个循环,结果显示是此读写锁写优先。即:加锁等待队列里写操作永远在读前面! 42 for(int i=0;i<2;i++) 43 { 44 pThrMgr->spawn((ACE_THR_FUNC)ThreadFunProducers); 45 ACE_OS::nanosleep (&t); 46 pThrMgr->spawn((ACE_THR_FUNC)ThreadFunConsumers); 47 ACE_OS::nanosleep (&t); 48 } 49 pThrMgr->wait(); 50 51 return 0; 52 }
4.运行结果
$ ./tt Thread ProducersLock begin NO:140070570608384 Thread ProducersLock end NO:140070570608384 Thread ProducersLock begin NO:140070549628672 Thread ProducersLock end NO:140070549628672 Thread ConsumersLock begin NO:140070560118528 Thread ConsumersLock end NO:140070560118528 Thread ConsumersLock begin NO:140070539138816 Thread ConsumersLock end NO:140070539138816
********************************************************************
高级线程(任务)ACE_Task_Base类来创建线程是更方便和优雅
5.示例代码
1 #include <iostream> 2 #include "ace/Task.h" 3 4 using namespace std; 5 6 //静态锁 7 struct Resource 8 { 9 static ACE_Thread_Mutex mutex; 10 static ACE_Condition<ACE_Thread_Mutex > cond; 11 }; 12 ACE_Thread_Mutex Resource::mutex; 13 ACE_Condition<ACE_Thread_Mutex > Resource::cond(Resource::mutex); 14 15 class ThreadProducers : public ACE_Task_Base { 16 public: 17 virtual int svc() 18 { 19 ACE_OS::sleep(1); 20 21 ACE_Guard<ACE_Thread_Mutex > guard(Resource::mutex); 22 cout<<"Thread ProducersLock begin NO:"<<ACE_Thread::self()<<endl; 23 24 cout<<"Thread ProducersLock end NO:"<<ACE_Thread::self()<<endl; 25 Resource::cond.signal(); 26 return 0; 27 } 28 }; 29 30 class ThreadConsumers : public ACE_Task_Base { 31 public: 32 virtual int svc() 33 { 34 ACE_Guard<ACE_Thread_Mutex > guard(Resource::mutex); 35 Resource::cond.wait(); 36 cout<<"Thread ConsumersLock begin NO:"<<ACE_Thread::self()<<endl; 37 38 cout<<"Thread ConsumersLock end NO:"<<ACE_Thread::self()<<endl; 39 return 0; 40 } 41 }; 42 43 44 int main(int argc, char *argv[]) 45 { 46 //1000纳秒=1ms 47 timespec_t t; 48 t.tv_sec=0;t.tv_nsec=1000; 49 50 ACE_Thread_Manager* pThrMgr = ACE_Thread_Manager::instance(); 51 //依次一读一写依次3个循环,结果显示是此读写锁写优先。即:加锁等待队列里写操作永远在读前面! 52 for(int i=0;i<2;i++) 53 { 54 ThreadProducers threadProducers; 55 ThreadConsumers threadConsumers; 56 threadProducers.activate(); 57 ACE_OS::nanosleep (&t); 58 threadConsumers.activate(); 59 ACE_OS::nanosleep (&t); 60 } 61 62 pThrMgr->wait(); 63 64 return 0; 65 }
6. 任务间通信
如前面所提到的,ACE中的每个任务都有一个底层消息队列(参见上面的图示)。这个消息队列被用作任务间通信的一种方法。当一个任务想要与另一任务“谈话”时,它创建一个消息,并将此消息放入它想要与之谈话的任务的消息队列。接收任务通常用getq()从消息队列里获取消息。如果队列中没有数据可用,它就进入休眠状态。如果有其他任务将消息插入它的队列,它就会苏醒过来,从队列中拾取数据并处理它。因而,在这种情况下,接收任务将从发送任务那里接收消息,并以应用特定的方式作出反馈。
下一个例子演示两个任务怎样使用它们的底层消息队列进行通信。这个例子包含了经典的生产者-消费者问题的实现。生产者任务生成数据,将它发送给消费者任务。消费者任务随后消费这个数据。使用ACE_Task构造,我们可将生产者和消费者看作是不同的ACE_Task类型的对象。这两种任务使用底层消息队列进行通信。
示例代码
1 #include "ace/Task.h" 2 3 //The Consumer Task. 4 class Consumer: 5 public ACE_Task<ACE_MT_SYNCH> 6 { 7 public: 8 int open(void*) 9 { 10 ACE_DEBUG((LM_DEBUG, "(%t) Consumer task opened \n")); 11 //Activate the Task 12 activate(THR_NEW_LWP,1); 13 return 0; 14 } 15 //The Service Processing routine 16 int svc(void) 17 { 18 //Get ready to receive message from Producer 19 ACE_Message_Block * mb =0; 20 do 21 { 22 mb=0; 23 //Get message from underlying queue 24 getq(mb); 25 ACE_DEBUG((LM_DEBUG, 26 "(%t)Got message: %d from remote task\n",*mb->rd_ptr())); 27 }while(*mb->rd_ptr()<3); 28 return 0; 29 } 30 int close(u_long) 31 { 32 ACE_DEBUG((LM_DEBUG,"(%t) Consumer closes down \n")); 33 return 0; 34 } 35 }; 36 37 class Producer: 38 public ACE_Task<ACE_MT_SYNCH> 39 { 40 public: 41 Producer(Consumer * consumer): 42 consumer_(consumer), data_(0) 43 { 44 mb_=new ACE_Message_Block((char*)&data_,sizeof(data_)); 45 } 46 int open(void*) 47 { 48 ACE_DEBUG((LM_DEBUG, "(%t) Producer task opened \n")); 49 //Activate the Task 50 activate(THR_NEW_LWP,1); 51 return 0; 52 } 53 //The Service Processing routine 54 int svc(void) 55 { 56 while(data_<4) 57 { 58 //Send message to consumer 59 ACE_DEBUG((LM_DEBUG, 60 "(%t)Sending message: %d to remote task\n",data_)); 61 consumer_->putq(mb_); 62 //Go to sleep for a sec. 63 ACE_OS::sleep(1); 64 data_++; 65 } 66 return 0; 67 } 68 int close(u_long) 69 { 70 ACE_DEBUG((LM_DEBUG,"(%t) Producer closes down \n")); 71 return 0; 72 } 73 private: 74 char data_; 75 Consumer * consumer_; 76 ACE_Message_Block * mb_; 77 }; 78 79 int main(int argc, char * argv[]) 80 { 81 ACE_DEBUG((LM_DEBUG,"(%t) Main begin. \n")); 82 Consumer *consumer = new Consumer; 83 Producer * producer = new Producer(consumer); 84 producer->open(0); 85 consumer->open(0); 86 //Wait for all the tasks to exit. 87 ACE_Thread_Manager::instance()->wait(); 88 ACE_DEBUG((LM_DEBUG,"(%t) Main end. \n")); 89 90 return 0; 91 }
$ ./tt (139897292330784) Main begin. (139897292330784) Producer task opened (139897292330784) Consumer task opened (139897292322560)Sending message: 0 to remote task (139897281832704)Got message: 0 from remote task (139897292322560)Sending message: 1 to remote task (139897281832704)Got message: 1 from remote task (139897292322560)Sending message: 2 to remote task (139897281832704)Got message: 2 from remote task (139897292322560)Sending message: 3 to remote task (139897281832704)Got message: 3 from remote task (139897281832704) Consumer closes down (139897292322560) Producer closes down (139897292330784) Main end.