线程调度器模拟:唤醒和睡眠Pthread的正确方法

时间:2014-09-28 23:28:15

标签: c++ multithreading pthreads scheduling condition-variable

我正在尝试使用First Come First Serve策略设计我自己的线程调度程序,我不确定我将线程置于睡眠状态并将其唤醒的方式是否正确。我正在使用C ++和Pthreads库。

我的想法是:

  • 主线程实例化工作线程。
  • 从工作线程调用单独的schedule()函数,表示应该调度调用线程。通过arrival timeidremaining time
  • schedule()内,创建我自己的Thread对象,该对象存储特定线程的arrival timeidremaining time属性(这些属性是我编造了)。 Thread对象也有自己的条件变量。
  • 每次调用schedule()函数时,都会创建一个Thread对象并将其添加到队列的后面。
  • Thread对象添加到队列后,调用schedule()的线程应等待其对应的条件变量。
  • 然后应该发信号通知队列前面的Thread对象的条件变量,表明它应该运行。所有其他线程应该等待各自Thread对象中的条件变量。

示例Threadqueue[0]queue[1]queue[2]queue[3]中存在5个queue[4]个对象}。由queue[0]表示的线程应该正在运行,queue[1]queue[2]queue[3]queue[4]表示的线程应该等待它们各自的条件变量。一旦队列[0]完成执行,它将从队列中删除,所有Thread对象将向前移动,并且将发信号通知新的queue[0]。如果我现在从新的工作线程调用schedule(),则应在Thread创建并添加新的queue[4]对象。然后调用线程应该等待queue[4]

为了测试这个设计,我写了一个例子。我省略了arrival timeidremaining time字段,因为它们在此时并不重要。以下是示例代码:

#include <iostream>
#include <string>
#include <vector>
#include <pthread.h>
using namespace std;

class Thread {
    public:
            pthread_cond_t conVar;
};

vector<Thread> queue;
pthread_mutex_t lock;

void schedule() {
    pthread_mutex_lock(&lock);
    cout << "Thread 1 locks the mutex\n";
    queue.push_back(first);
    pthread_cond_wait(&(queue.back()).conVar,&lock);
}

void *worker(void *arg) {

    Thread first;
    cout << "Thread 1 adding to queue. Going for the wait...\n";

    schedule();

    cout << "Got out of the wait. Let's do some work\n";

    for(int i = 0; i < 20; i++)
            cout << i << " ";

    cout << "\n";

    pthread_exit(NULL);
}

int main() {


    vector<Thread> queue;
    pthread_t a;

    pthread_create(&a,NULL,worker,NULL);
    cout << "Sleeping in the main thread for a bit....\n";
    sleep(1);

    cout << "Now let's signal the Thread object in the queue\n";

    int result = pthread_mutex_trylock(&lock);
    if(result != 0)
            sleep(3);
    pthread_cond_signal(&(queue.front()).conVar);
    pthread_mutex_unlock(&lock);
    pthread_join(a,NULL);


    return 0;

}

我已经多次尝试过这个示例代码,并且主线程总是先执行并尝试发出队列前面的信号。工作线程永远不会及时获取队列以插入Thread对象,并且我不断得到段错误,因为主线程试图发出不存在的条件变量的信号。

我的问题是:这种设计是一种有效的方法,可以将线程置于休眠状态并将其作为调度算法的一部分唤醒它们吗?或者主线程是否总是先执行并尝试发出空队列信号?

1 个答案:

答案 0 :(得分:0)

'main'线程只是一个碰巧由OS加载程序而不是用户代码创建的线程。它不以任何方式“特殊”。

一个问题是您正在尝试将线程与睡眠调用同步。这不会很好。

如果你想尝试这个,先用另一种方式发出信号。将condvar传递给工人并在main中等待它。当工作人员将自己插入队列时,它可以发出condvar信号,以便main可以继续。