在C++中实现二进制信号量类

Ben*_*ton 1 c++ semaphore pthreads

所以,我正在我的一个班级中安排一个调度程序.基本上,我们假装一次只能执行一个线程.我们应该使用信号量类来允许这些线程阻塞自己来模拟等待CPU的线程.

问题是,线程似乎在错误的时间阻塞并在错误的时间执行.我想知道我是否缺少对信号量的概念性理解以及如何实现它.我想知道我是否能对我的实施得到一些反馈.教师提供了这个头文件,我没有以任何方式修改过:

class Semaphore {
private:
  int             value;
  pthread_mutex_t m;
  pthread_cond_t  c;

public:

  /* -- CONSTRUCTOR/DESTRUCTOR */

  Semaphore(int _val);

  //~Semaphore();

  /* -- SEMAPHORE OPERATIONS */

  int P();
  int V();
};
Run Code Online (Sandbox Code Playgroud)

这是我使用posix东西的实现:

Semaphore::Semaphore(int _val){
    value = _val;
    c = PTHREAD_COND_INITIALIZER;
    m = PTHREAD_MUTEX_INITIALIZER;
}

int Semaphore::P(){
    if(value <= 0){
        pthread_cond_wait(&c, &m);
    }
    value--;
}

int Semaphore::V(){
    value++;
    if(value > 0){
        pthread_cond_signal(&c);
    }
}
Run Code Online (Sandbox Code Playgroud)

Kaz*_*Kaz 9

你忽略了锁定互斥锁.

其次,你在这里有一个计数信号量,而不是二进制信号量.二进制信号量只有两个状态,因此bool变量是合适的:

class Semaphore {
private:
  bool            signaled;   // <- changed
  pthread_mutex_t m;
  pthread_cond_t  c;

  void Lock() { pthread_mutex_lock(&m); }          // <- helper inlines added
  void Unlock() { pthread_mutex_unlock(&m); }
public:

  /* -- CONSTRUCTOR/DESTRUCTOR */

  Semaphore(bool);

  //~Semaphore();

  /* -- SEMAPHORE OPERATIONS */

  void P();   // changed to void: you don't return anything
  void V();
};
Run Code Online (Sandbox Code Playgroud)

IMPL:

// consider using C++ constructor initializer syntax.

Semaphore::Semaphore(bool s){        // don't use leading underscores on identifiers
    signaled = s;
    c = PTHREAD_COND_INITIALIZER;    // Not sure you can use the initializers this way!
    m = PTHREAD_MUTEX_INITIALIZER;   // they are for static objects.

    // pthread_mutex_init(&m); // look, this is shorter!
}

void Semaphore::P(){
    Lock();              // added
    while (!signaled){   // this must be a loop, not if!
        pthread_cond_wait(&c, &m);
    }
    signaled = false;
    Unlock();
}

void Semaphore::V(){
    bool previously_signaled;
    Lock();
    previusly_signaled = signaled; 
    signaled = true;
    Unlock();  // always release the mutex before signaling
    if (!previously_signaled)
      pthread_cond_signal(&c); // this may be an expensive kernel op, so don't hold mutex
}
Run Code Online (Sandbox Code Playgroud)