Linux C、如何安排10个等待线程FIFO执行?
Linux C, How to schedule 10 waiting threads to execute in FIFO?
我正在使用以下条件线程使用 FIFO 调度锁定 10 个线程,我需要按照线程到达的顺序解锁线程 pthread_cond_wait(&cvv, &lock);
我需要知道这是否可能,或者不能保证会出现这种情况。
struct sched_param param = {.sched_priority = 10};
pthread_cond_t cvv = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
void *thread(void *v) {
pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m);
int index = *((int *)v);
printf("Locking [%d] and waiting\n", index);
pthread_mutex_lock(&lock);
pthread_cond_wait(&cvv, &lock);
printf("Unlockd [%d] => %d\n", index, clock());
pthread_mutex_unlock(&lock);
return NULL;
}
int main(int argc, char** argv) {
for (int i = 0; i < 10; i++) {
t = (pthread_t *) malloc(sizeof (pthread_t));
int *x = malloc(sizeof (int));
*x = i;
pthread_create(t, NULL, thread, x);
}
for (int i = 0; i < 10; i++) {
pthread_cond_signal(&cvv);
}
}
输出未按上升顺序排列
Locking [0] and waiting
Locking [1] and waiting
Locking [2] and waiting
Locking [3] and waiting
Locking [4] and waiting
Locking [5] and waiting
Locking [6] and waiting
Locking [7] and waiting
Locking [8] and waiting
Locking [9] and waiting
Unlocked [0] => 7043
Unlocked [8] => 7084
Unlocked [6] => 7100
Unlocked [2] => 7130
Unlocked [5] => 7294
Unlocked [7] => 7362
Unlocked [3] => 7407
Unlocked [1] => 7463
Unlocked [9] => 7482
Unlocked [4] => 7559
十个互斥体或信号量怎么样。一切都开始锁定。每个线程等待一个锁,一旦完成工作,它就会为下一个线程 (n + 1) 解锁锁。最后一个线程将解锁第一个锁。
或者说,线程的顺序只会执行一次,为什么要用线程呢?如果这是练习的要求,并且最后一个线程的结束就是你程序的结束,那么线程应该在为下一个线程解锁锁后退出,最后一个线程根本没有锁可以解锁。然后主线程(您的 main
函数)等待(通过 pthread_join
)所有线程完成。
线程函数的伪代码:
void *function(void *)
{
wait(lock[n]);
// Do work...
unlock(lock[n + 1]);
}
据我所知,没有特殊的方法可以让争用同一资源的线程按顺序排列。这适用于信号量,我认为也适用于条件变量。 OS 将简单地调度优先级最高的线程首先争用资源。
因此您必须有 10 个独立的同步原语(信号量、条件变量等),每个原语用于一个线程。
顺便说一句,你输出的第一部分的顺序很好,只是运气好;绝对没有什么可以保证对 pthread_create 的连续调用实际上会在那里然后按该顺序产生新线程 运行。
pthread_setschedparam
可能对您不可用,因为它需要权限。您不检查这些调用的 return 值,但您可能会发现它们失败并显示 EPERM
。他们为我这样做。
I need to unlock the threads in the order with which they have arrived
to pthread_cond_wait(&cvv, &lock); I need to know if that is possible
or there is no guarantee to have this scenario.
是的,你可以这样做,但你需要自己动手。这是一个可以实现它的方案:
建立三个全局计数器,比如in
、out
和next
,对它们的访问受互斥量保护。全部初始化为0.
每个线程像这样通过锁:
- 在等待 CV 之前,它递增
in
并记录新值。这是它的 "ticket".
- 它测试它的票是否等于
next
并且 next
小于或等于 out
,并且仅当这些条件之一或两个都满足时才等待 CV没遇到。
- 如果确实等待,那么当它 returns 时,它会循环返回以根据
next
. 的当前值测试其票证
- 在通过锁定之前,它递增
next
。
- 最后,它向 CV 广播(这可能在解锁互斥锁之前或之后)
解锁下一个话题,
- 递增
out
- 如果
next
仍然是 0 那么也增加它
- 调用
pthread_cond_broadcast
(不pthread_cond_signal
)
当然,所有对in
、out
和next
的访问都必须在互斥量的保护下进行,这应该与CV使用的相同。
请注意,该方案允许线程在当前没有线程被锁定时授予预期的解锁。这实际上将解决您当前实现的问题之一,但如果您愿意,您可以仅使用 in
和 next
对其进行返工,使执行解锁的线程等待 in
超过next
。这可以通过使用相同的简历来实现。详情留作练习。
我正在使用以下条件线程使用 FIFO 调度锁定 10 个线程,我需要按照线程到达的顺序解锁线程 pthread_cond_wait(&cvv, &lock); 我需要知道这是否可能,或者不能保证会出现这种情况。
struct sched_param param = {.sched_priority = 10};
pthread_cond_t cvv = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
void *thread(void *v) {
pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m);
int index = *((int *)v);
printf("Locking [%d] and waiting\n", index);
pthread_mutex_lock(&lock);
pthread_cond_wait(&cvv, &lock);
printf("Unlockd [%d] => %d\n", index, clock());
pthread_mutex_unlock(&lock);
return NULL;
}
int main(int argc, char** argv) {
for (int i = 0; i < 10; i++) {
t = (pthread_t *) malloc(sizeof (pthread_t));
int *x = malloc(sizeof (int));
*x = i;
pthread_create(t, NULL, thread, x);
}
for (int i = 0; i < 10; i++) {
pthread_cond_signal(&cvv);
}
}
输出未按上升顺序排列
Locking [0] and waiting
Locking [1] and waiting
Locking [2] and waiting
Locking [3] and waiting
Locking [4] and waiting
Locking [5] and waiting
Locking [6] and waiting
Locking [7] and waiting
Locking [8] and waiting
Locking [9] and waiting
Unlocked [0] => 7043
Unlocked [8] => 7084
Unlocked [6] => 7100
Unlocked [2] => 7130
Unlocked [5] => 7294
Unlocked [7] => 7362
Unlocked [3] => 7407
Unlocked [1] => 7463
Unlocked [9] => 7482
Unlocked [4] => 7559
十个互斥体或信号量怎么样。一切都开始锁定。每个线程等待一个锁,一旦完成工作,它就会为下一个线程 (n + 1) 解锁锁。最后一个线程将解锁第一个锁。
或者说,线程的顺序只会执行一次,为什么要用线程呢?如果这是练习的要求,并且最后一个线程的结束就是你程序的结束,那么线程应该在为下一个线程解锁锁后退出,最后一个线程根本没有锁可以解锁。然后主线程(您的 main
函数)等待(通过 pthread_join
)所有线程完成。
线程函数的伪代码:
void *function(void *)
{
wait(lock[n]);
// Do work...
unlock(lock[n + 1]);
}
据我所知,没有特殊的方法可以让争用同一资源的线程按顺序排列。这适用于信号量,我认为也适用于条件变量。 OS 将简单地调度优先级最高的线程首先争用资源。
因此您必须有 10 个独立的同步原语(信号量、条件变量等),每个原语用于一个线程。
顺便说一句,你输出的第一部分的顺序很好,只是运气好;绝对没有什么可以保证对 pthread_create 的连续调用实际上会在那里然后按该顺序产生新线程 运行。
pthread_setschedparam
可能对您不可用,因为它需要权限。您不检查这些调用的 return 值,但您可能会发现它们失败并显示 EPERM
。他们为我这样做。
I need to unlock the threads in the order with which they have arrived to pthread_cond_wait(&cvv, &lock); I need to know if that is possible or there is no guarantee to have this scenario.
是的,你可以这样做,但你需要自己动手。这是一个可以实现它的方案:
建立三个全局计数器,比如
in
、out
和next
,对它们的访问受互斥量保护。全部初始化为0.每个线程像这样通过锁:
- 在等待 CV 之前,它递增
in
并记录新值。这是它的 "ticket". - 它测试它的票是否等于
next
并且next
小于或等于out
,并且仅当这些条件之一或两个都满足时才等待 CV没遇到。 - 如果确实等待,那么当它 returns 时,它会循环返回以根据
next
. 的当前值测试其票证
- 在通过锁定之前,它递增
next
。 - 最后,它向 CV 广播(这可能在解锁互斥锁之前或之后)
- 在等待 CV 之前,它递增
解锁下一个话题,
- 递增
out
- 如果
next
仍然是 0 那么也增加它 - 调用
pthread_cond_broadcast
(不pthread_cond_signal
)
- 递增
当然,所有对in
、out
和next
的访问都必须在互斥量的保护下进行,这应该与CV使用的相同。
请注意,该方案允许线程在当前没有线程被锁定时授予预期的解锁。这实际上将解决您当前实现的问题之一,但如果您愿意,您可以仅使用 in
和 next
对其进行返工,使执行解锁的线程等待 in
超过next
。这可以通过使用相同的简历来实现。详情留作练习。