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

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

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

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

 

4线程管理ACE同步和线程管理机制

 

  ACE拥有许多不同的用于创建和管理多线程程序的类。在这一章里,我们将查看ACE中的一些线程管理机制。在一开始,我们将查看那些简单的线程包装类,它们的管理功能很少。但是,随着内容的进展,我们将查看ACE_Thread_Manager中的更为强大的管理机制。ACE还拥有一组非常全面的处理线程同步的类。这些类也将在本章讲述。

 

4.1创建和取消线程

  在不同的平台上,有着若干不同的用于线程管理的接口。其中包括POSIX pthreads接口、Solaris线程、Win32线程等等。这些接口提供了相同或是相似的功能,但是它们的API的差别却极为悬殊。这就导致了困难、麻烦和易错的编程,因为应用程序员必须熟悉不同平台上的若干接口。而且,这样写下的程序,是不可移植和不灵活的。

  ACE_Thread提供了对OS的线程调用的简单包装,这些调用处理线程创建、挂起、取消和删除等问题。它提供给应用程序员一个简单易用的接口,可以在不同的线程API间移植。ACE_Thread是非常“瘦”的包装,有着很少的开销。其大多数方法都是内联的,因而等价于对底层OS专有线程接口的直接调用。ACE_Thread中的所有方法都是静态的,而且该类一般不进行实例化。

  下面的例子演示怎样使用ACE_Thread包装类创建、生成和联接(join)线程。

 

4-1

#include "ace/Thread.h"

#include "ace/Synch.h"

 

static int number=0;

static int seed = 0;

 

static void* worker(void *arg)

{

ACE_UNUSED_ARG(arg);

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

::number++;

ACE_DEBUG((LM_DEBUG," and number is %d\n",::number));

 

//Let the other guy go while I fall asleep for a random period

//of time

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

 

//Exiting now

ACE_DEBUG((LM_DEBUG,

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

 

return 0;

}

 

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

{

if(argc<2)

{

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

ACE_OS::exit(1);

}

 

ACE_OS::srand(::seed);

 

//setup the random number generator

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

 

//number of threads to spawn

ACE_thread_t *threadID = new ACE_thread_t[n_threads+1];

ACE_hthread_t *threadHandles = new ACE_hthread_t[n_threads+1];

if(ACE_Thread::spawn_n(threadID, //id’s for each of the threads

n_threads, //number of threads to spawn

(ACE_THR_FUNC)worker, //entry point for new thread

0, //args to worker

THR_JOINABLE | THR_NEW_LWP, //flags

ACE_DEFAULT_THREAD_PRIORITY,

0, 0, threadHandles)==-1)

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

 

//spawn n_threads

for(int i=0; i

ACE_Thread::join(threadHandles[i]);

 

//Wait for all the threads to exit before you let the main fall through

//and have the process exit.

return 0;

}

 

在这个简单的例子中,创建了n_thread个工作者线程。每个线程都执行程序中定义的worker()函数。线程是通过使用ACE_Thread::spawn_n()调用创建的。要作为线程的执行启动点调用的函数的指针(在此例中为worker()函数)被作为参数传入该调用中。要注意的重点是ACE_Thread::spawn_n()要求所有的线程启动函数(方法)必须是静态的或全局的(就如同直接使用OS线程API时所要求的一样)。

  一旦工作者函数启动,它将全局变量number的值加1,报告它的当前值,然后进入休眠状态,以把处理器让给其他线程。sleep()休眠一段随机长度的时间。在线程醒来后,它将number的当前值通知给用户,然后退出worker()函数。

  一旦线程从它的启动函数返回,它在线程库上隐含地发出线程exit()调用并退出。这样一旦“掉出”worker()函数,工作者线程也就退出了。负责创建工作者线程的主线程,在退出之前“等待”所有其他的线程完成它们的执行并退出。当主线程退出时(通过退出main()函数),整个进程也将被销毁。这之所以会发生是因为每当线程退出main()函数时,都会隐含地调用exit(3c)函数。因此,如果主线程没有被强制等待其他线程结束,当它死掉时,进程将会被自动销毁,并在它的所有工作者线程完成工作之前销毁它们!

  上面所说的等待是通过使用ACE_Thread::join()调用来完成的。该方法的参数是你想要主线程与之联接的线程的句柄(ACE_hthread_t)。

  在此例中有若干事实值得注意。首先,在该类中没有可供我们调用的管理功能,用以在内部记住应用所派生的线程的ID。这使得我们难以联接(join())、杀死(kill())或是一般性地管理我们派生的线程。在本章后面讲述的ACE_Thread_Manager缓解了这些问题,一般说来,应该使用ACE_Thread_Manager而不是线程包装API

  其次,在程序中没有使用同步原语来保护全局数据。在此例中,它们并不是必须的,因为所有的线程都只对全局变量执行一次加操作。但是在实际应用中,为了保护所有共享互斥数据(全局或静态变量),比如说全局的number变量,“锁”将会是必需的。

 

4.2 ACE同步原语

  ACE有若干可用于同步目的的类。这些类可划分为以下范畴:

 

  • ACE Lock类属
  • ACE Guard类属
  • ACE Condition类属
  • 杂项ACE Synchronization

 

4.2.1 ACE Lock类属

  锁类属包含的类包装简单的锁定机制,比如互斥体、信号量、读/写互斥体和令牌。在这一类属中可用的类在表4-1中显示。每个类名后都有对用法和用途的简要描述:

 

名字

描述

ACE_Mutex

封装互斥机制(根据平台,可以是mutex_tpthread_mutex_t等等)的包装类,用于提供简单而有效的机制来使对共享资源的访问序列化。它与二元信号量(binary semaphore)的功能相类似。可被用于线程和进程间的互斥。

ACE_Thread_Mutex

可用于替换ACE_Mutex,专用于线程同步。

ACE_Process_Mutex

可用于替换ACE_Mutex,专用于进程同步。

ACE_NULL_Mutex

提供了ACE_Mutex接口的“无为”(do-nothing)实现,可在不需要同步时用作替换。

ACE_RW_Mutex

封装读者/作者锁的包装类。它们是分别为读和写进行获取的锁,在没有作者在写的时候,多个读者可以同时进行读取。

ACE_RW_Thread_Mutex

可用于替换ACE_RW_Mutex,专用于线程同步。

ACE_RW_Process_Mutex

可用于替换ACE_RW_Mutex,专用于进程同步。

ACE_Semaphore

这些类实现计数信号量,在有固定数量的线程可以同时访问一个资源时很有用。在OS不提供这种同步机制的情况下,可通过互斥体来进行模拟。

ACE_Thread_Semaphore

应被用于替换ACE_Semaphore,专用于线程同步。

ACE_Process_Semaphore

应被用于替换ACE_Semaphore,专用于进程同步。

ACE_Token

提供“递归互斥体”(recursive mutex),也就是,当前持有某令牌的线程可以多次重新获取它,而不会阻塞。而且,当令牌被释放时,它确保下一个正阻塞并等待此令牌的线程就是下一个被放行的线程。

ACE_Null_Token

令牌接口的“无为”(do-nothing)实现,在你知道不会出现多个线程时使用。

ACE_Lock

定义锁定接口的接口类。一个纯虚类,如果使用的话,必须承受虚函数调用开销。

ACE_Lock_Adapter

基于模板的适配器,允许将前面提到的任意一种锁定机制适配到ACE_Lock接口。

 

4-1 ACE锁类属中的类

TAG: 线程管理 同步

41/41234>
 

评分:0

我来说两句

seccode