http://hi.baidu.com/653701wwww/blog/item/9d787c00e961bb8fe950cdb9.html
锁类属包含的类包装简单的锁定机制,比如互斥体、信号量、读/写互斥体和令牌。在这一类属中可用的类在表4-1
中显示。每个类名后都有对用法和用途的简要描述:
名字 |
描述 |
ACE_Mutex |
封装互斥机制(根据平台,可以是 mutex_t 、 pthread_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 接口。 |
表 表 互斥体实现了“互相排斥
”( 任何线程在进入临界区之前,必须获取
( 什么时候需要使用互斥体呢?互斥体用于保护共享的易变代码,也就是,全局或静态数据。这样的数据必须通过互斥体进行保护,以防止它们在多个线程同时访问时损坏。 下面的例子演示 例 #include "ace/Synch.h" #include "ace/Thread.h" //Arguments that are to be passed to the worker thread are passed //through this struct. struct 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;i<arg->iterations_;i++) { ACE_DEBUG((LM_DEBUG, "(%t) Trying to get a hold of this iteration/n")); //This is our critical section arg->mutex_.acquire(); ACE_DEBUG((LM_DEBUG,"(%t) This is iteration number %d/n",i)); ACE_OS::sleep(2); //simulate critical work arg->mutex_.release(); } return 0; } int main(int argc, char*argv[]) { if(argc<2) { ACE_OS::printf("Usage: %s <number_of_threads> <number_of_iterations>/n", argv[0]); ACE_OS::exit(1); } Args arg(ACE_OS::atoi(argv[2])); //Setup the arguments int n_threads = ACE_OS::atoi(argv[1]); //determine the number of threads to be spawned. 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<n_threads; 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; } 在上面的例子中, 在此例中,一开始,每个线程立即进入 如前面所提到的,各种互斥体锁应被直接用于你的代码,或者,如果需要灵活性,作为模板参数来使用。但是,如果你需要动态地(也就是在运行时)改变你的代码所用锁的类型,就无法使用这些锁。 为应对这个问题, 下面的例子演示 例 #include "ace/Synch.h" #include "ace/Thread.h" //Arguments that are to be passed to the worker thread are passed //through this class. struct Args { public: Args(ACE_Lock* lock,int iterations): mutex_(lock),iterations_(iterations){} ACE_Lock* mutex_; int iterations_; }; //The starting point for the worker threads static void* worker(void*arguments) { Args *arg= (Args*) arguments; for(int i=0;i<arg->iterations_;i++) { ACE_DEBUG((LM_DEBUG, "(%t) Trying to get a hold of this iteration/n")); //This is our critical section arg->mutex_->acquire(); ACE_DEBUG((LM_DEBUG,"(%t) This is iteration number %d/n",i)); ACE_OS::sleep(2); //simulate critical work arg->mutex_->release(); } return 0; } int main(int argc, char*argv[]) { if(argc<4) { ACE_OS::printf("Usage: %s <number_of_threads> <number_of_iterations> <lock_type>/n", argv[0]); ACE_OS::exit(1); } //Polymorphic lock that will be used by the application ACE_Lock *lock; //Decide which lock you want to use at run time, //recursive or non-recursive. if(ACE_OS::strcmp(argv[3],"Recursive")) lock=new ACE_Lock_Adapter<ACE_Recursive_Thread_Mutex>; else lock=new ACE_Lock_Adapter<ACE_Thread_Mutex> //Setup the arguments Args arg(lock,ACE_OS::atoi(argv[2])); //spawn threads and wait as in previous examples.. } 在此例中,和前面的例子唯一的不同是 如表 递归锁允许同一线程多次获取同一个锁。线程不会因为试图获取它已经拥有的锁而死锁。这些类型的锁能在各种不同
的情况下派上用场。例如,如果你用一个锁来维护跟踪流的一致性,你可能希望这个锁是递归的,因为某个方法可以调用一个跟踪例程,获取锁,被信号中断,然后
再尝试获取这个跟踪锁。如果锁是非递归的,线程将会在这里锁住它自己。你会发现很多其他需要递归锁的有趣应用。重要的是要记住,你获取递归锁多少次,就必须释放
它多少次。 在 尽管 例 #include "ace/Token.h" #include "ace/Thread.h" //Arguments that are to be passed to the worker thread are passed //through this struct. struct Args { public: Args(int iterations): token_(“myToken”),iterations_(iterations){} ACE_Token token_; int iterations_; }; //The starting point for the worker threads static void* worker(void*arguments) { Args *arg= (Args*) arguments; for(int i=0;i<arg->iterations_;i++) { ACE_DEBUG((LM_DEBUG,"(%t) Trying to get a hold of this iteration/n")); //This is our critical section arg->token_.acquire(); ACE_DEBUG((LM_DEBUG,"(%t) This is iteration number %d/n",i)); //work ACE_OS::sleep(2); arg->token_.release(); } return 0; } int main(int argc, char*argv[]) { //same as previous examples.. }