简体   繁体   English

线程调度程序仿真:唤醒和休眠Pthread的正确方法

[英]Thread Scheduler Simulation: Correct Way to Wake Up and Sleep a Pthread

I am trying to design my own thread scheduler using a First Come First Serve strategy, and I'm not sure whether the way I put threads to sleep and wake them up is the correct approach. 我正在尝试使用“先来先服务”策略设计自己的线程调度程序,但不确定将线程置于睡眠状态并唤醒它们的方法是否正确。 I am using C++ and the Pthreads library. 我正在使用C ++和Pthreads库。

My idea is this: 我的想法是这样的:

  • Main thread instantiates a worker thread. 主线程实例化工作线程。
  • Separate schedule() function gets called from a worker thread denoting that the calling thread should be scheduled. 从工作线程调用单独的schedule()函数,该函数指示应对调用线程进行调度。 Passes in an arrival time , id , remaining time . 传入arrival timeidremaining time
  • Within schedule() , create my own Thread object which stores the arrival time , id , and remaining time attributes of a particular thread (these are attributes that I made up). schedule() ,创建我自己的Thread对象,该对象存储特定线程的arrival timeidremaining time属性(这些是我组成的属性)。 The Thread object also has its own condition variable. Thread对象也有其自己的条件变量。
  • Every time the schedule() function gets called, a Thread object will be created and added to the back of the queue. 每次调用schedule()函数时,都会创建一个Thread对象并将其添加到队列的后面。
  • Once the Thread object has been added to the queue, the thread that called schedule() should wait on its corresponding condition variable. Thread对象添加到队列后,调用schedule()的线程应等待其对应的条件变量。
  • Then the condition variable of the Thread object at the front of the queue should be signaled, indicating that it should run. 然后,应该用信号通知队列前面的Thread对象的条件变量,表明它应该运行。 All other threads should wait on the condition variables in their respective Thread objects. 所有其他线程应在其各自的Thread对象中等待条件变量。

Example : 5 Thread objects exist in queue[0] , queue[1] , queue[2] , queue[3] , and queue[4] . 示例 :在queue[0]queue[1]queue[2]queue[3]queue[4]存在5个Thread对象。 The thread represented by queue[0] should be running, and the threads represented by queue[1] , queue[2] , queue[3] , and queue[4] should be waiting on their respective condition variables. queue[0]表示的线程应该正在运行,并且由queue[1]queue[2]queue[3]queue[4]表示的线程应该等待它们各自的条件变量。 Once queue[0] finishes executing, it will get removed from the queue, all the Thread objects will be moved forward, and the new queue[0] will be signaled to run. 一旦queue [0]完成执行,它将被从队列中删除,所有Thread对象将被向前移动,并发出新的queue[0]发出信号。 If I call schedule() from a new worker thread now, a new Thread object should be created and added at queue[4] . 如果现在从新的工作线程中调用schedule() ,则应创建一个新的Thread对象,并将其添加到queue[4] The calling thread should then wait on queue[4] . 然后,调用线程应在queue[4]queue[4]

To test out this design, I wrote an example. 为了测试这种设计,我写了一个例子。 I omitted the arrival time , id , and remaining time fields because they are not important at this point. 我省略了arrival timeidremaining time字段,因为它们在这一点上并不重要。 Here is the example code: 这是示例代码:

#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;

}

I have tried this example code several times, and the main thread always executes first and tries to signal the front of the queue. 我已经多次尝试了此示例代码,并且主线程始终先执行并尝试向队列前端发出信号。 The worker thread never gets the queue in time to insert the Thread object, and I keep getting a segfault because the main thread tries to signal a condition variable that doesn't exist. 工作线程从不及时获取插入Thread对象的队列,而我一直在遇到段错误,因为主线程试图发信号通知不存在的条件变量。

My question is this : Is this design a valid way to put threads to sleep and wake them up as part of a scheduling algorithm? 我的问题是 :这种设计是否是使线程进入睡眠状态并将其作为调度算法的一部分唤醒的有效方法? Or will the main thread always execute first and try to signal an empty queue? 还是主线程总是总是先执行并尝试发出空队列信号?

The 'main' thread is just a thread that happens to be created by the OS loader instead of by user code. “主”线程只是一个由操作系统加载程序而非用户代码创建的线程。 It is not 'special' in any way. 它在任何方面都不是“特殊的”。

One problem is that you are trying to synchronize threads with sleep calls. 一个问题是您试图将线程与睡眠调用同步。 This will not end well. 这不会很好地结束。

If you want to try this, signal the other way first. 如果要尝试此操作,请先以其他方式发出信号。 Pass a condvar to the worker and wait on it in main. 将condvar传递给工作人员,然后在主等待。 When the worker has inserted itself into the queue, it can signal the condvar so that main can continue. 当工作人员将自己插入队列后,它可以向condvar发信号,以便main可以继续。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM