我想使用先来先服务策略来设计我自己的线程调度程序,但我不确定是否将线程放入睡眠状态并唤醒它们up是正确的方法。我正在使用C++和Pthreads库。线程调度模拟:正确的唤醒方式和睡眠线程
我的想法是这样的:
- 主线程实例化一个工作线程。
- 单独
schedule()
函数从工作线程调用,表示调用线程应该被调度。通过arrival time
,id
,remaining time
。 - 在
schedule()
,创建自己的Thread
对象存储特定线程的arrival time
,id
和remaining time
属性(这些都是我提出了属性)。Thread
对象也有其自己的条件变量。 - 每次调用
schedule()
函数时,都会创建一个Thread
对象并将其添加到队列的后面。 - 一旦
Thread
对象已被添加到队列中,调用schedule()
的线程应等待其相应的条件变量。 - 然后,应该发信号通知队列前面的
Thread
对象的条件变量,表明它应该运行。所有其他线程都应该等待它们各自的Thread
对象中的条件变量。
例:5 Thread
对象queue[0]
,queue[1]
,queue[2]
,queue[3]
,和queue[4]
存在。由queue[0]
代表的线程应该正在运行,并且由queue[1]
,queue[2]
,queue[3]
和queue[4]
表示的线程应当等待它们各自的条件变量。一旦队列[0]完成执行,它将从队列中移除,所有Thread
对象将向前移动,并且新的queue[0]
将被标记为运行。如果我现在从新的工作线程中调用schedule()
,则应该创建一个新的Thread
对象并将其添加到queue[4]
。调用线程应等待queue[4]
。
为了测试这个设计,我写了一个例子。我省略了arrival time
,id
和remaining 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
对象,并且我不断收到段错误,因为主线程尝试发出一个不存在的条件变量的信号。
我的问题是这样的:这种设计是一种有效的方法,可以将线程挂起并作为调度算法的一部分来唤醒它们吗?或者主线程总是先执行并尝试发信号通知空队列?
我只看到一个Thread对象和没有schedule()方法。注意,因为线程第一次被分配在worker()的堆栈上,所以在worker退出时会超出范围 – 2014-09-28 23:40:56
@ KC-NH是的,worker应该是Thread的成员函数,Thread实例应该和operator一起动态分配新的,很多的东西:) – 2014-09-28 23:51:07
你只有一个锁。该锁是否保护队列?在持有全局锁定时进入等待状态并不奏效。 – 2014-09-29 13:35:07