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 }
Condition.cpp

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
result:

 

 

********************************************************************

高级线程(任务)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 }
Condition.cpp

 

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 }
View Code
$ ./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. 
View Code

 

posted on 2015-01-15 18:46  光标  阅读(375)  评论(0编辑  收藏  举报

导航