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, &param);
    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.

是的,你可以这样做,但你需要自己动手。这是一个可以实现它的方案:

  • 建立三个全局计数器,比如inoutnext,对它们的访问受互斥量保护。全部初始化为0.

  • 每个线程像这样通过锁:

    • 在等待 CV 之前,它递增 in 并记录新值。这是它的 "ticket".
    • 它测试它的票是否等于 next 并且 next 小于或等于 out,并且仅当这些条件之一或两个都满足时才等待 CV没遇到。
    • 如果确实等待,那么当它 returns 时,它会循环返回以根据 next.
    • 的当前值测试其票证
    • 在通过锁定之前,它递增 next
    • 最后,它向 CV 广播(这可能在解锁互斥锁之前或之后)
  • 解锁下一个话题,

    • 递增out
    • 如果 next 仍然是 0 那么也增加它
    • 调用pthread_cond_broadcastpthread_cond_signal

当然,所有对inoutnext的访问都必须在互斥量的保护下进行,这应该与CV使用的相同。

请注意,该方案允许线程在当前没有线程被锁定时授予预期的解锁。这实际上将解决您当前实现的问题之一,但如果您愿意,您可以仅使用 innext 对其进行返工,使执行解锁的线程等待 in 超过next。这可以通过使用相同的简历来实现。详情留作练习。