贝贝花花包包店,精品555皮具,钱夹,皮夹

字体: | 推荐给好友 上一篇 | 下一篇

ACE程序员教程-第4章 线程管理:ACE的同步和线程管理机制

发布: 2008-6-13 14:28 | 作者: Umar Syyid | 来源: 转载 | 查看: 330次

4.2.2 ACE守卫(Guard)类属

  ACE中的守卫用于自动获取和释放锁。守卫类的对象定义一个代码块,在其上获取一个锁。在退出此代码块时,锁被自动释放。

  ACE中的守卫类是一种模板,它通过所需锁定机制的类型来参数化。底层的锁可以是ACE Lock类属中的任何类,也就是,任何互斥体或锁类。它是这样工作的:对象的构造器获取锁,析构器释放锁。表4-2列出了ACE中可用的守卫:

 

名字

描述

ACE_Guard

自动在底层锁上调用acquire()release()。任何ACE Lock类属中的锁都可以作为它的模板参数传入。

ACE_Read_Guard

自动在底层锁上调用acquire()release()

ACE_Write_Guard

自动在底层锁上调用acquire()release()

 

4-2 ACE中的守卫

 

  下面的例子演示怎样使用看守:

 

4-5

#include "ace/Synch.h"

#include "ace/Thread.h"

 

//Arguments that are to be passed to the worker thread are passed

//through this class.

class Args

{

public:

Args(int iterations):

mutex_(),iterations_(iterations){}

ACE_Thread_Mutex mutex_;

int iterations_;

};

 

//The starting point for the worker threads

static void* worker(void*arguments)

{

Args *arg= (Args*) arguments;

for(int i=0;iiterations_;i++)

{

ACE_DEBUG((LM_DEBUG,"(%t) Trying to get a hold of this iteration\n"));

ACE_Guard guard(arg->mutex_);

{

//This is our critical section

ACE_DEBUG((LM_DEBUG,"(%t) This is iteration number %d\n",i));

 

//work

ACE_OS::sleep(2);

}//end critical section

}

 

return 0;

}

 

int main(int argc, char*argv[])

{

//same as previous example

}

 

  在上面的例子中,守卫在工作者线程中管理临界区。守卫对象从ACE_Guard模板类创建而来。守卫应使用的锁的类型被传给模板。通过将所需获取的实际锁对象经由守卫对象的构造器传入,程序创建守卫对象。该锁由ACE_Guard在内部自动获取,所以for循环中的区域就是受保护的临界区。一旦出了作用域,看守对象就会被自动删除,锁也随之被释放。

  守卫是很有用的,因为它们保证一旦你获取了一个锁,你总是会释放它(当然,除非你的线程因为无法预料的情况而死掉)。在有许多不同的返回路径的复杂方法中,这被证明为是极其有用的。

 

4.2.3 ACE条件(Condition)类属

  ACE_Condition类是针对OS条件变量原语的包装类。那么,到底什么是条件变量呢?

  线程常常需要特定条件被满足才能继续它的操作。例如,设想线程需要在全局消息队列里插入消息。在插入任何消息之前,它必须检查在消息队列里是否有空闲空间。如果消息队列在“满”状态,它就什么也不能做,而必须进行休眠,过一会再重试。就是说,在访问全局资源之前,某个条件必须为真。然后,当另外的线程空出消息队列时,应该有方法通知或发信号给原来的线程:在消息队列里有位置了,现在应该再次尝试插入消息。这可以使用条件变量来完成。条件变量不是被用作互斥原语,而是用作特定条件已经满足的指示器。

  在使用条件变量时,你的程序应该完成以下步骤:

 

  • 获取全局资源(例如,消息队列)的锁(互斥体)。
  • 检查条件(例如,消息队列里有空间吗?)。
  • 如果条件失败,调用条件变量的wait()方法。等待在未来条件变为真。
  • 当另一线程在全局资源上执行操作时,它发信号(signal())给所有其他在此资源上测试条件的线程(例如,另一线程从消息队列中取出一个消息,然后通过条件变量发送信号,以使阻塞在wait()上的线程能够再尝试将它们的消息插入队列)。
  • 在醒来之后,重新检查条件现在是否为真。如为真,则在全局资源上执行操作(例如,将消息插入全局消息队列)

  需要特别注意的是,在阻塞在wait调用中之前,条件变量机制(也就是ACE_Cond)负责释放全局资源上的互斥体。如果没有进行此操作,将没有其他的线程能够在此资源上工作(该资源是条件改变的原因)。同样,一旦阻塞线程收到信号、重又醒来,它在检查条件之前会在内部重新获取锁。

  下面的例子是对本章第一个例子的改写。如果你还记得,我们曾说过使用ACE_Thread::join()调用可以使主线程等待其他的线程结束。另一种达到同样目的的方法是使用条件变量,它使主线程在退出之前等待“所有线程已经结束”条件为真。最后一个线程可以通过条件变量发信号给等待中的主线程,通知它所有线程已经结束、而它是最后一个。随后主线程继续执行,退出应用并销毁进程。如下如示:

 

4-6

#include "ace/Thread.h"

#include "ace/Synch.h"

 

static int number=0;

static int seed=0;

 

class Args

{

public:

Args(ACE_Condition *cond, int threads):

cond_(cond), threads_(threads){}

ACE_Condition *cond_;

int threads_;

};

 

static void* worker(void *arguments)

{

Args *arg= (Args*)arguments;

ACE_DEBUG((LM_DEBUG,"Thread (%t) Created to do some work\n"));

::number++;

 

//Work

ACE_OS::sleep(ACE_OS::rand()%2);

 

//Exiting now

ACE_DEBUG((LM_DEBUG,

"\tThread (%t) Done! \n\tThe number is now: %d\n",number));

 

//If all threads are done signal main thread that

//program can now exit

if(number==arg->threads_)

{

ACE_DEBUG((LM_DEBUG,

"(%t) Last Thread!\n All threads have done their job!

Signal main thread\n"));

arg->cond_->signal();

}

 

return 0;

}

 

int main(int argc, char *argv[])

{

if(argc<2)

{

ACE_DEBUG((LM_DEBUG,

"Usage: %s \n", argv[0]));

ACE_OS::exit(1);

}

 

int n_threads=ACE_OS::atoi(argv[1]);

 

//Setup the random number generator

ACE_OS::srand(::seed);

 

//Setup arguments for threads

ACE_Thread_Mutex mutex;

ACE_Condition cond(mutex);

Args arg(&cond,n_threads);

 

//Spawn off n_threads number of threads

for(int i=0; i

{

if(ACE_Thread::spawn((ACE_THR_FUNC)worker,(void*)&arg,

THR_DETACHED|THR_NEW_LWP)==-1)

ACE_DEBUG((LM_DEBUG,"Error in spawning thread\n"));

}

 

//Wait for signal indicating that all threads are done and program

//can exit. The global resource here is “number” and the condition

//that the condition variable is waiting for is number==n_threads.

mutex.acquire();

 

while(number!=n_threads)

cond.wait();

ACE_DEBUG((LM_DEBUG,"(%t) Main Thread got signal. Program

exiting..\n"));

 

mutex.release();

 

ACE_OS::exit(0);

}

 

注意主线程首先获取一个互斥体,然后对条件进行测试。如果条件不为真,主线程就等待在此条件变量上。条件变量随即自动释放互斥体,并使主线程进入睡眠。条件变量总是像这样与互斥体一起使用。这是一种可如下描述的一般模式[1]

 

while( expression NOT TRUE ) wait on condition variable;

 

记住条件变量不是用于互斥,而是用于我们所描述的发送信号功能。

  除了ACE_Condition类,ACE还包括ACE_Condition_Thread_Mutex类,它使用ACE_Thread_Mutex作为全局资源的底层锁定机制。

43/4<1234>
 

评分:0

我来说两句

seccode