【问题标题】:pthread_yield doesn't properly cycle between threadspthread_yield 没有在线程之间正确循环
【发布时间】:2019-09-19 08:58:48
【问题描述】:

我有三个函数 A、B、C,我想将它们用于线程。我想将它们运行一定数量的迭代,并希望在每次迭代时在它们之间切换。我在使用 pthread_yield() 时遇到了他们的执行顺序问题

下面是这些函数的代码

void *A(void *arg){
int i = 0;
for (i=0; i < 3; i++){
    printf("Hello A%d\n", i);
    pthread_yield();
    }
}

void *B(void *arg){
    int i = 0;
    for(i=0; i < 3; i++){
        printf("Hello B%d\n", i);
        pthread_yield();
    }
}

void *C(void *arg){
    int i = 0;
    for(i=0; i < 3; i++){
        printf("Hello C%d\n", i);
        pthread_yield();
    }
}

这是我制作线程的主要功能的代码

int main(){

    pthread_t threadId_1, threadId_2, threadId_3;

    printf("Before Thread\n"); 
    pthread_create(&threadId_1, NULL, A, NULL); 
    pthread_create(&threadId_2, NULL, B, NULL); 
    pthread_create(&threadId_3, NULL, C, NULL); 
    // This line is Equivalent to Sleep // pthread_join(threadId_1, NULL); 
    //pthread_join(threadId_2, NULL);
    //pthread_join(threadId_3, NULL);
    sleep(1);
    printf("After Thread\n");

}

当我运行程序时,我得到以下输出:

Before Thread
Hello C0
Hello B0
Hello C1
Hello B1
Hello C2
Hello B2
Hello A0
Hello A1
Hello A2
After Thread

我想要的不是这个

Before Thread
Hello A0
Hello B0
Hello C0
Hello A1
Hello B1
Hello C1
Hello A2
Hello B2
Hello C2
After Thread

如果我不使用 pthread_yield,我最后创建的线程将首先完成,然后是倒数第二个,最先创建的线程将最后完成。为什么会这样?

另外,当我使用 pthread_yield 时,为什么程序在完成执行之前在最后两个创建的线程 B 和 C 之间交替,然后移动到线程 A?

如何在线程 A、B、C 完美交替的情况下实现我想要的输出?

【问题讨论】:

  • 我正在使用 c++。
  • 如果您不使用 pthread_yeild(),线程可以按任意顺序执行,您可以尝试在循环中添加更多迭代并检查结果。 pthread_yeild() 将当前线程放入等待队列并安排另一个线程运行。现在,可以先打印 A0、B0、C0 中的任何一个,因为您已经从 main 对 A、B 和 C 进行了 3 次调用。假设先调用C,然后打印C0,线程回到等待队列,另一个线程将被执行,可以是A或B(“A0”或“B0”中的任何一个都可以被打印)。因此,这种方法不适合您需要的结果。
  • 来自文档:“pthread_yield() 旨在与实时调度策略(即 SCHED_FIFO 或 SCHED_RR)一起使用。将 pthread_yield() 与非确定性调度策略(如 SCHED_OTHER)一起使用是未指定的,非常可能意味着您的应用程序设计已损坏。”
  • @AkshitAchara 你是对的。以前我尝试过 3 到 10 次迭代。现在我尝试了 100 次迭代。在前几次迭代中,只有 B 和 C 被调度,然后 A 也开始被调度。我很惊讶为了看到“理想”的结果,我需要增加迭代次数。
  • 它在哪里说它应该“在线程之间正确循环”?

标签: c++ multithreading pthreads


【解决方案1】:

man pthread_yield

导致调用线程放弃 CPU。该线程以其静态优先级被放置在运行队列的末尾,另一个线程被调度运行。 如果调用线程是当时最高优先级列表中的唯一线程,它将继续运行。

换句话说,pthread_yield 不保证暂停线程。因此,它不能帮助排序或序列化线程的执行。这对你的任务来说是一个错误的工具。


我有三个函数 A、B、C,我想将它们用于线程。我想将它们运行一定数量的迭代,并希望在每次迭代时在它们之间切换。

一种解决方案是让一个线程依次运行函数A、B和C。

另一种解决方案是将线程固定到同一个 CPU 并分配实时 FIFO 优先级,以便pthread_yield 切换到另一个等待在同一个 CPU 上运行的 FIFO 实时线程。但是,在这种情况下,并行性会丢失,从而破坏了拥有多个线程的初衷。

【讨论】:

  • 来自硬实时系统的人通常期望比例如更多的控制和确定性。 Linux 提供。通常,Pthreads 和 Posix 机制的定义过于松散(有充分的理由)。使 Linux 更接近硬实时的一件事是 SCHED_DEADLINE。
猜你喜欢
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-24
  • 1970-01-01
  • 1970-01-01
  • 2013-04-22
相关资源
最近更新 更多