线程调度程序模拟:唤醒和睡眠Pthread的正确方法
Thread Scheduler Simulation: Correct Way to Wake Up and Sleep a Pthread
我正在尝试使用"先到先得"策略设计自己的线程调度程序,我不确定让线程休眠和唤醒它们的方式是否正确。我使用的是C++和Pthreads库。
我的想法是:
- 主线程实例化一个工作线程
- 从工作线程调用单独的
schedule()
函数,表示应该调度调用线程。传入一个arrival time
、id
、remaining time
- 在
schedule()
中,创建我自己的Thread
对象,该对象存储特定线程的arrival time
、id
和remaining time
属性(这些是我创建的属性)。Thread
对象也有自己的条件变量 - 每次调用
schedule()
函数时,都会创建一个Thread
对象并将其添加到队列的后面 - 一旦
Thread
对象被添加到队列中,调用schedule()
的线程就应该等待其相应的条件变量 - 然后,应该用信号通知队列前面的
Thread
对象的条件变量,指示它应该运行。所有其他线程都应该等待它们各自的Thread
对象中的条件变量
示例:queue[0]
、queue[1]
、queue[2]
、queue[3]
和queue[4]
中存在5个Thread
对象。由queue[0]
表示的线程应该正在运行,由queue[1]
、queue[2]
、queue[3]
和queue[4]
表示的线程应当等待它们各自的条件变量。一旦队列[0]完成执行,它将从队列中删除,所有的Thread
对象都将向前移动,并且新的queue[0]
将被通知运行。如果我现在从一个新的工作线程调用schedule()
,那么应该在queue[4]
处创建并添加一个新Thread
对象。调用线程应该在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 mutexn";
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 workn";
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 queuen";
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
对象,我一直得到一个segfault,因为主线程试图用信号通知一个不存在的条件变量。
我的问题是:作为调度算法的一部分,这种设计是让线程休眠并唤醒它们的有效方法吗?还是主线程总是先执行,然后尝试发出空队列的信号?
"main"线程只是一个碰巧由操作系统加载程序而不是用户代码创建的线程。它在任何方面都不"特别"。
一个问题是,您正试图将线程与睡眠调用同步。这不会有好的结局。
如果你想试试这个,先用另一种方式发信号。将condvar传递给worker,并在main中等待它。当worker将自己插入队列时,它可以向condvar发出信号,以便main可以继续。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- 在 pthread 中运行 shell 命令的良好和优化方法是什么?
- 将类方法作为 pthread start 函数传递
- 在 for 循环中将结构传递给 pthread 的正确方法
- pthread以并行方式运行类实例的方法
- 线程调度程序模拟:唤醒和睡眠Pthread的正确方法
- c++:如何定义类方法作为线程的启动例程(使用pthread库)