第 4章 线程管理:ACE 的同步和线程管理机制

第 4章 线程管理:ACE 的同步和线程管理机制

标签ACE  线程  机制  管理  2008-12-10 09:16
出自:《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)线程。
 
#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 <number of threads>/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 thread
                            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<n_threads; i++)
        ACE_Thread::join(threadHandles[i]);
//Wait for all the threads to exit before you let the main fall throug
//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变量,“锁”将会是必需的。
 
2008.12.10 haha123_0 Code::Blocks 8.02 ACE 5.6.7编译通过:)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值