c - Linux C,如何安排 10 个等待线程在 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
解决方案
pthread_setschedparam
您可能无法使用,因为它需要特权。您不检查这些调用的返回值,但您可能会发现它们以EPERM
. 他们为我这样做。
我需要按照线程到达 pthread_cond_wait(&cvv, &lock); 的顺序解锁线程 我需要知道这是否可能,或者不能保证会出现这种情况。
是的,你可以这样做,但你需要自己动手。这是一个可以实现它的方案:
建立三个全局计数器,例如
in
、out
和next
,对它们的访问受互斥锁保护。将它们全部初始化为 0。每个线程都像这样通过锁:
- 在等待 CV 之前,它会递增
in
并记录新值。这是它的“票”。 - 它测试其票证是否等于
next
和next
小于或等于out
,并且仅当不满足其中一个或两个条件时才等待 CV。 - 如果它确实等待,那么当它返回时,它会循环返回以针对
next
. - 在它通过锁之前,它会递增
next
. - 最后,它向 CV 广播(这可能是在解锁互斥锁之前或之后)
- 在等待 CV 之前,它会递增
解锁下一个线程,
- 增量
out
- 如果
next
仍为 0,则也将其递增 - 打电话
pthread_cond_broadcast
(不pthread_cond_signal
)
- 增量
当然,所有对in
、out
和的访问都next
必须在互斥锁的保护下执行,该互斥锁应该与 CV 使用的相同。
请注意,当当前没有线程被锁定时,该方案允许线程前瞻性地授予解锁。这实际上将解决您当前实现的一个问题,但如果您愿意,您可以仅使用in
and对其进行重新设计next
,使执行解锁的线程等待in
超过next
。这可以通过使用相同的 CV 来实现。细节留作练习。
推荐阅读
- excel - 如何按名称删除带有 VBA 的 ActiveX 按钮?
- python - 将 rpyc 远程 stdio 重定向到流
- python - 如何从枢轴操作合并回数据框?
- parse-platform - 如何为数组字段中的指针添加权限指针?
- java - Intellij Idea 上的 Kafka 生产者给出语法错误
- linux - 如何在linux中配置连接到usb的调制解调器?
- ios - macbook m1中没有发生这样的模块'firebase'错误
- vba - 打印为 PDF 时从 Excel 工作表重命名 Word 宏
- javascript - Dash React 下拉组件:无法从浏览器控制台打开
- c# - json .net 5 blazor中的日期时间空序列化如何