|
使用ACE_Task_Base类来对线程进行管理:
我们可以把线程的各种属性标志作为参数传递给ACE_Task_Base::active()方法,这样就可以创建具有某种或某些特殊属性的线程了;这些属性定义了线程将怎样被创建、调度、销毁等等;
线程创建标志:
THR_CANCEL_DISABLE : 不允许这个线程被取消;
THR_CANCEL_ENABLE : 允许这个线程被取消;
THR_CANCEL_DEFERRED: 只允许延迟的取消;
THR_BOUND : 创建一个线程,并绑定到一个可由内核调度的实体上;
THR_NEW_LWP : 创建一个内核级线程;该标志影响进程的并发属性;对"未绑定线程"来说,其预想的并发级别是增1,也就是添加一个新的内核线程到可用的线程池中,以运行用户线程;在不支持N:M混合线程模型的OS平台上,该标志会被忽略;
THR_DETACHED : 创建一个分离的线程;这就意味着这个线程的退出状态不能被其它线程访问;当这个线程退出的时候,其线程ID和它所占用的资源会被OS自动回收;
THR_JOINABLE : 允许新创建的线程被"会合(join)";这就意味着这个线程的退出状态能够被其它线程访问,可以通过join()方法来访问它的退出状态,但是它的线程ID和它所占用的资源不会被OS回收;所有ACE线程创建方法的默认行为都是THR_JOINABLE;
THR_SUSPENDED : 创建一个线程,但让其处在挂起状态;
THR_DAEMON : 创建一个看守(daemon)线程;
THR_SCHED_FIFO : 如果可用,使用FIFO政策调度新创建的线程;
THR_SCHED_RR : 如果可用,使用round-robin方案调度新创建的线程;
THR_SCHED_DEFAULT : 使用操作系统上可用的无论哪种默认调度方案;
THR_SCOPE_SYSTEM : 新线程在系统调度争用空间中创建,永久绑定于新创建的内核线程;
THR_SCOPE_PROCESS : 新线程在进程调度争用空间中创建,也就是说,它将作为一个用户线程运行;
线程的这些属性标志通过逻辑或运算符"|"串在一起,并把它作为ACE_Task_Base::active()方法的第一个参数传递给该方法;如:
ACE_Task_Base:active(THR_NEW_LWP | THR_SCHED_DEFAULT | THR_SUSPENDED | THR_JOINABLE);
调度竞争范围:
大多数OS都在内核级线程和用户级线程之间作出了区分;内核级线程是这样的可调度实体:OS知道它们,并且会通过内核级的调度器对它们进行调度.而另一方面,用户级线程是量级更轻的线程,由基于库的调度器在进程的地址空间中对其进行调度.这样的线程允许速度更快的上下文切换,但是可能会被阻塞.作为程序员,你只能处理用户级线程.你的进程会得到一个内核线程池,用于调度你所有的用户级线程;你可以使用THR_BOUND标志显式地把一个用户级线程绑定到一个特定的内核线程上去;这样被绑定的用户级线程的调度就会使用底层的内核级线程来完成;
如果你指定要在创建线程时使用THR_NEW_LWP标志,那么,你可以确信,一个新的内核级可调度实体也将被创建;也就是说,这个新的用户级线程被绑定到一个新的内核级线程上;这是ACE_Task_Base::active()方法的默认行为;但是,如果你指定了自己的属性标志参数,并且没有包含THR_NEW_LWP标志,那么线程库就会创建一个用户级线程;
一旦ACE_Task_Base::active()方法返回,OS就已经创建了一个新的线程了;但是,这并没有说明关于新线程的当前运行状态的任何情况;OS会使用其特有的某种内部调度方案来决定何时运行新线程.所以,即使线程已经创建,当active()方法返回时,它也未必就在运行;
通过指定THR_SUSPENDED标志,你可以在一定程度上控制线程的初始运行状态.这个标志会使OS创建处在挂起状态的新线程;你可以调用resume()方法来激活这个处于挂起状态的新线程而让它开始运行;
线程的优先级和调度类:
大多数OS都会以自己的方式来定义线程的优先级;例如:Solaris定义的优先级范围是0--127,127是最高优先级;Windows定义的优先级范围是0--15,15是最高优先级;而VxWorks定义的优先级是0--255,0是最高优先级;
大多数通用OS都只提供了一种分时调度类;分时调度器尝试以这样的方式来保证公平性:优先级最高的线程能够执行一段有限的时间(称为时间片:time slice).如果在正在执行的线程用完其时间片之前,有优先级更高的线程变得可以运行,则优先级较低的线程就会被占先,而优先级较高的线程会开始使用其时间片;
还有些OS实现了实时调度类;在支持分时调度类的OS中,实时调度类中的线程所处的优先级总是比分时类中的任何线程的优先级都要高;换句话说,在同时支持分时调度类和实时调度类的OS中,实时调度类中的所有线程的优先级都比分时调度类中的线程的优先级要高;
在实时调度类中提供了两种调度政策:
A、round-robin:由一个时间量指定、在被同一优先级的其它实时线程占先之前、某个线程所能运行的最大时间;
B、先进先出(FIFO):优先级最高的的线程可以随意运行任意长的时间,直到它自愿让出CPU控制权,或被优先级更高的实时线程占先为止;
线程优先级宏:
ACE_THR_PRI_OTHER_MIN: 分时调度类的最低优先级;
ACE_THR_PRI_OTHER_DEF: 分时调度类的默认优先级;
ACE_THR_PRI_OTHER_MAX: 分时调度类的最高优先级;
ACE_THR_PRI_RR_MIN : 采用round-robin调度政策的实时调度类的最低优先级;
ACE_THR_PRI_RR_DEF : 采用round-robin调度政策的实时调度类的默认优先级;
ACE_THR_PRI_RR_MAX : 采用round-robin调度政策的实时调度类的最高优先级;
ACE_THR_PRI_FIFO_MIN : 采用FIFO调度政策的实时调度类的最低优先级;
ACE_THR_PRI_FIFO_DEF : 采用FIFO调度政策的实时调度类的默认优先级;
ACE_THR_PRI_FIFO_MAX : 采用FIFO调度政策的实时调度类的最高优先级;
我们在使用这些优先级的时候,要确保这些优先级参数能在所使用的OS平台上正确工作;如果没有指定调度类,那么默认使用的就是分时调度类,也称为"其它";
注意:你必须自己负责设置能在你的应用中正确工作的线程优先级.在这个问题上,ACE没有提供多少帮助;你一定要确保传递给active()方法的值的工作方式正是你想要的;
线程池:
ACE_Task_Base类和ACE_Task<T>类模板的active()方法不但可以创建单个线程,而且也可以一次性地创建多个线程,所有这些线程都是从同一个svc()方法进入点开始执行;在创建一个任务内的一组线程的时候,ACE会在内部把一个组标识符赋值给任务内的所有线程,可以通过grp_id()方法来访问它,并用于后续的组管理操作;这样创建的所有线程共享同一个ACE_Task_Base类的对象会者是共享同一个ACE_Task<>类的对象,但是这组线程中的每个线程都拥有自己独立的栈资源;
必须注意:在使用线程组的时候,不要让线程组中的所有工作线程都锁在同一个资源上,以致于事情变得更糟糕;因为加锁开销可能会高得足以抵消使用多线程所获得的任何性能上的提高;
更多文章,欢迎访问http://blog.csdn.net/wallwind
|
|