C++全局变量虽然有时候很有用,但也可能带来有害的副作用和不确定的初始化语义,从而产生微妙的问题。在“多线程”应用程序中,这些问题还会加剧。特别是,当多个线程同时访问“未同步的全局变量”时,信息有可能丢失,或者,会使用错误的信息。
操作系统提供的原始TSS C API存在以下问题:
容易出错
不可移植
如果在每一个应用程序中都要去处理这些问题,那将十分麻烦,而且容易出错;所以ACE提供了ACE_TSS类。
例子:
下面例子中,演示如何将ACE_TSS运用到“一个链接一个线程”中,每一个线程都可以得到“线程专有存储空间”中的请求数(request count).采用这一设计,我们无需互斥体(mutex)就可以消除“请求数”上的“竞态条件(race condition)”。此外,当使用“线程专有存储空间”时,那些“容易出错,不可移植”的原始C API所具有的任何“偶发复杂性”在此也不复存在。
首先定义一个简单的类,用来跟踪“请求数”
class Request_Count{
public:
Request_Count():count_(0){}
void increment(){ ++count_; }
int value() const { return count_; }
private:
int count_;
};
请注意,Request_Count 对“线程专有存储”一无所知。然后,将这个类作用ACE_TSS模板的类型参数:
static ACE_TSS<Request_Count> request_count;
现在,每一个线程都各有一个 Request_Count的副本,能通过request_count访问。虽然这个对象在“逻辑上”似乎是“全局”的---也就是说,可以像访问文件范围中任何其他对象一样访问它,但是,它的状态(state)在物理上是“局部”存在于使用它的线程中的。将request_count集成到handle_date()方法中很简单,如下所示:
virtual int handle_date(ACE_SOCK_Stream *){
while (logging_handler_log_record()!=-1)
request_count->intcrement();
ACE_DEBUG((LM_DEBUG,"request_count= %d/n",request_count->value()));
}