4.2.2.1 锁(lock)类属

来源:互联网 发布:java new date 格式化 编辑:程序博客网 时间:2024/06/14 03:06

4.2.2.1 锁(lock)类属

标签:  lock  2008-12-07 13:47
4.2.2.1 锁(lock)类属

 Mutex / Thread_Mutex / Process_Mutex  互斥体. 获得它的线程才能进入临界区.
  // 例子代码 : Thread_Mutex 类的用win32 api的简单实现:
  class Thread_Mutex {
  public:
   Thread_Mutex ( ) {
    InitializeCriticalSection (&lock_);
   }
   ~Thread_Mutex ( ) {
    DeleteCriticalSection (&lock_);
   }
   int acquire ( ) {  //获取对互斥体的锁定
    EnterCriticalSection (&lock_); return 0;
   }
   int release ( ) {  //释放锁定
    LeaveCriticalSection (&lock_); return 0;
   }
  private:
   // Win32 serialization mechanism.
   CRITICAL_SECTION lock_;
  };

 RW_Mutex / RW_Thread_Mutex / RW_Process_Mutex 读写互斥体. 用在读多写少的情况下.

 Semaphore / Thread_Semaphore / Process_Semaphore  信号量. 通过原子的增减一个整数来管理.
  // 例子代码: Semaphore的简单实现:
  class Semaphore {
  public:
   Semaphore (int initial_value): count_nonzero_ (lock_) {
    Guard<Thread_Mutex> monitor (lock_);
    count_ = initial_value;
   }
   void acquire (void) {
    Guard<Thread_Mutex> monitor (lock_);
    while (count_ == 0)
     count_nonzero_.wait ();  //当信号量的计数为0时. 等待.
    count_ = count_ - 1;
   }
   void release (void) {
    Guard<Thread_Mutex> monitor (lock_);
    if (count_ == 0)
     count_nonzero_.signal ();
    count_ = count_ + 1;
   }
   private:
    Thread_Mutex lock_;
    Condition<Thread_Mutex> count_nonzero_;  //通过条件对象实现
    u_int count_;
   };

 Null_Mutex  一种0开销的互斥体(它的锁定/解锁函数是空的内联函数. 所以没有运行时开销. 用在不需要同步的情况下
  //例子代码: Null_Mutex类的简单实现:
  class Null_Mutex {
  public:
   Null_Mutex (void) {}
   ~Null_Mutex (void) {}
   int remove (void) { return 0; }
   int acquire (void) const { return 0; }
   int try_acquire (void) const { return 0; }
   int release (void) const { return 0; }
  };

 Token 令牌环. 它和Mutex相比更为通用. 因为它实现了"递归互斥体"语义(拥有锁的线程可以重新获得该锁). 并且它对阻塞在该
  令牌环上的线程以FIFO(先进先出)的顺序被服务(而Mutex没有这种顺序). 
  // Token的接口如下:
  class Token {
  public:
   Token (const char *name = 0, void * = 0);
   ~Token (void);
   int acquire (void (*sleep_hook)(void *),
   void *arg = 0,
   Time_Value *timeout = 0);
   int acquire (Time_Value *timeout = 0);
   virtual void sleep_hook (void);
   int renew (int requeue_position = 0, Time_Value *timeout = 0);
   int tryacquire (void);
   int remove (void);
   int release (void);
   int waiters (void);
   thread_t current_owner (void);
  };   

 Recursive_Thread_Mutex 这个类貌似只用在Solaris中. 因为Solaris缺省提供的互斥体是非递归的(即拥有该锁的线程不可以再次
  获得该锁). 所以提供了这个类. (在Win32和 POSIX Pthreads中提供的是递归锁. 不存在这个问题).  
  
 
4.2.2.2 Guard类属

 Guard / Write_Guard / Read_Guard 用它的构造函数和析构函数来 获取和释放 锁.
  // 例子代码. Guard类的简单实现:
  class Guard {  
  public:
   Guard(const Thread_Mutex & m) : lock_(m) {
    lock_.acquire(); //让锁定和解锁自动化
   }
   ~Guard() {
    lock_.release();
   }
  private:
   const Thread_mutex & lock_;
  };

 Thread_Control  不知作用....以后补....
 
4.2.2.3 Condition类属
 Condition  条件. 应该和Java中 java.util.concurrent.locks.Condition 的作用一样.
 Null_Condition  它提供了0开销的Condition实现. 用来在不需要同步的时候使用(和Null_Mutex类似).
  // Condition类的接口 :
  template <class MUTEX>
  class Condition {
  public:
   Condition(const MUTEX &m, int type = USYNC_THREAD, void *arg = 0); //通过锁来构造条件对象.
   ~Condition();
   int remove();  //要这个函数干啥???
   int wait(Time_Value *abstime = 0) const;  // 等待
   int signal() const;  //通知一个等待的线程.
   int broadcast() const; //通知所有等待线程.
  }


 
4.2.2.6 其它类属

 Thread  线程类  这个类中的一些静态函数用于线程的创建等.
   它是一个原始的东西. 通常应该使用Thread_Manager类而不是它.

 atomic_Ops  封装了对于内置数据类型(如int)的算术操作(如++).  使这种操作成为线程安全的(原子的).
   //例子代码
   template <class TYPE>
   class Atomic_Op {
   public:
    Atomic_Op (void) { count_ = 0; }
    Atomic_Op (TYPE c) { count_ = c; }
    TYPE operator++ (void)  { //封装了内置类型的算术运算. 使它成为线程安全的.(还有其它的类似++的运算符)
     Guard monitor (lock_);
     return ++count_;
    }
    operator TYPE () {  //取内部数据类型的值. 返回的是该数据当前值的拷贝.
     Guard monitor_ (lock_);
     return count_;
    }
    // Other arithmetic operations omitted...
   private:
    Thread_Mutex lock_;
    TYPE count_;
   };
   

4.5.4 ACE线程管理器类

4.5.4.1 Thread_Manager类.  //这节的笔记来自<<中篇: ACE程序员教程>> 4.3节
 它用来管理成组的线程 和 任务(ACE_Task). 
 它比ACE_Thread类的功能更多. 它不仅可以创建/销毁一组线程. 还可以对它们挂起和恢复.
 也可以发送信号给某一组线程. 或者是在一组线程上等待.
 这个类使用了单件模式. 用 ACE_Thread_Manager* Thr_Manager = ACE_Thread_Manager::instance() 来取得该对象.
 
 /////////////////////////////////////////////////////////////////////
 // 使用Thread_Manager来管理线程的例子. (来自<<ACE程序员教程>>49页)
 /////////////////////////////////////////////////////////////////////

 
 // 演示怎么使用ACE_Thread_Manager类来对线程组进行 挂起/恢复
 // 以及协作式撤销(就是对线程设置一个状态.让该线程的代码检测该状态后退出).
 
 #include "ace/Thread_Manager.h"
 
 static const int DEFAULT_THREADS = ACE_DEFAULT_THREADS;
 static const int DEFAULT_ITERATIONS = 100000;
 
 static void * worker (int iterations) { 
  for (int i = 0; i < iterations; i++) {
   if ((i % 1000) == 0) {  //每循环1000次检测一下"当前线程是否正请求撤销".
    ACE_DEBUG ((LM_DEBUG, "(%t) checking cancellation before iteration %d!/n", i));
    //用单件ACE_Thread_Manager对象的testcancel()来测试是否撤销一个线程.
    // 所以看上去ACE_Thread::self()可以取得当前正在执行的线程(ACE_thread_t).
    if (ACE_Thread_Manager::instance ()->testcancel (ACE_Thread::self ()) != 0) {
     ACE_DEBUG ((LM_DEBUG, "(%t) has been canceled before iteration %d!/n",i));
     break;
    }
   }
  }
  return 0;
 }
 int main (int argc, char *argv[])
 {
  int n_threads = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_THREADS;  //线程数
  int n_iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_ITERATIONS;  //线程函数中的循环的次数.
  
  ACE_Thread_Manager *thr_mgr = ACE_Thread_Manager::instance ();  //取得单件的线程管理器对象
  
  // 下边的 ACE_Thread_Manager::spawn_n()创建的是一组线程们.
  // 在本例子中是创建一组共n_threads个线程.
  // 这一组线程都执行第2个参数指定的线程函数.
  // 第3个参数指定将要传递给线程函数的参数. 第4个是一些旗标. 默认THR_NEW_LWP|THR_JOINABLE|THR_INHERIT_SCHED.
  // 还有其它一些参数. 指定线程堆栈. 优先级等. 这个函数除了前两个参数外都有默认值.
  // 它返回创建的这个线程组的组ID.
  int grp_id = thr_mgr->spawn_n (
   n_threads,  //这个线程组的线程数
   ACE_THR_FUNC (worker),  //这组线程的线程函数
   (void *) n_iterations,  // 传递给线程函数的参数.
   THR_NEW_LWP | THR_DETACHED); //旗标.
   
  ACE_OS::sleep (1);   //主线程休息1秒.
  
  ACE_DEBUG ((LM_DEBUG, "(%t) suspending group/n"));
  if (thr_mgr->suspend_grp (grp_id) == -1) //让一组线程挂起
   ACE_ERROR ((LM_DEBUG, "(%t) %p/n", "Could not suspend_grp"));
   
  ACE_OS::sleep (1);
  ACE_DEBUG ((LM_DEBUG, "(%t) resuming group/n"));
  if (thr_mgr->resume_grp (grp_id) == -1)  // 让一组线程唤醒
   ACE_ERROR ((LM_DEBUG, "(%t) %p/n", "resume_grp"));
  // Wait for 1 more second and then cancel all the threads.
  ACE_OS::sleep (ACE_Time_Value (1));
  ACE_DEBUG ((LM_DEBUG, "(%t) canceling group/n"));
  if (thr_mgr->cancel_grp (grp_id) == -1)  // 请求一组线程撤销. 所以线程函数中要有配合的代码. 如worker()所示.
   ACE_ERROR ((LM_DEBUG, "(%t) %p/n", "cancel_grp"));
  //  等待线程管理器中所有的线程结束.
  thr_mgr->wait ();
  return 0;
 }

 

4.5.6 其它类

TSS(线程专有存储)
 ACE中使用模板类ACE_TSS来解决"线程专有存储"的问题. 它的使用很简单:
 需要成为线程专有的类被传入ACE_TSS 模板. 然后可以使用C++的->操作符来调用它的全部公共方法.
 (原理是不是在该类的 operator-> 函数中先取得当前线程的句柄. 再根据线程句柄映射到该线程专有的对象上)
 ///////////////////////////////////////////////////////////
 // 使用ACE_TSS的一个例子. 来自<<ace程序员教程>>4.4节 51页
 ///////////////////////////////////////////////////////////
 #include "ace/Synch.h"
 #include "ace/Thread_Manager.h"
 class DataType {
 public:
  DataType():data(0){}
  void increment(){ data++;}
  void set(int new_data){ data=new_data;}
  void decrement(){ data--;}
  int get(){return data;}
 private:
  int data;
 };

 // 构造全局的线程专有对象. 是不是很简单?
 ACE_TSS<DataType> data; 
 
 // 测试线程1. 其中使用全局的 data. 但实际上它们使用的是各自的线程专有的.
 static void* thread1(void*) {
  data->set(10);
  ACE_DEBUG((LM_DEBUG,"(%t)The value of data is %d /n",data->get()));
  for(int i=0;i<5;i++)
  data->increment();
  ACE_DEBUG((LM_DEBUG,"(%t)The value of data is %d /n",data->get()));
  return 0;
 }
 
 // 测试线程2. 其中使用全局的data. 但实际上它们使用的是各自的线程专有的.
 static void * thread2(void*) {
  data->set(100);
  ACE_DEBUG((LM_DEBUG,"(%t)The value of data is %d /n",data->get()));
  for(int i=0; i<5;i++)
  data->increment();
  ACE_DEBUG((LM_DEBUG,"(%t)The value of data is %d /n",data->get()));
  return 0;
 }
 
 int main(int argc, char*argv[]) {
  // 注意这里的ACE_Thread_Manager::spawn()函数. 它和spawn_n()很相似. 但它只创建一个线程.
  ACE_Thread_Manager::instance()->spawn((ACE_THR_FUNC)thread1,0,THR_NEW_LWP|THR_DETACHED);
  ACE_Thread_Manager::instance()->spawn((ACE_THR_FUNC)thread2,0,THR_NEW_LWP| THR_DETACHED);
  // 等待线程管理器中所有的线程结束.
  ACE_Thread_Manager::instance()->wait();
  ACE_DEBUG((LM_DEBUG,"Both threads done.Exiting.. /n"));
 }

原创粉丝点击