【问题标题】:Why dosen't the parent thread calling pthread_yield make child threads run first?为什么调用 pthread_yield 的父线程不让子线程先运行?
【发布时间】:2021-07-23 11:05:55
【问题描述】:

这是我的代码。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sched.h>

void *helper(void *arg)
{
    printf("HELPER\n");
    return NULL;
}

int main()
{
    pthread_t thread;
    pthread_create(&thread, NULL, &helper, NULL);
    pthread_yield();
    // sched_yield();
    printf("MAIN\n");
    
    pthread_join(thread, NULL);
    return 0;
}

使用 pthread_yield()sched_yield(),输出总是:

MAIN
HELPER

我了解到的两个事实让我假设 HELPER 会在 MAIN 之前打印:

  1. 调用 pthread_yield 会导致调用线程放弃 CPU。 线程以其静态优先级被放置在运行队列的末尾,并安排另一个线程运行。如果调用线程是当时最高优先级列表中的唯一线程,它将继续运行。
  2. 子线程的创建优先级与父线程相同。

HELPER打印在MAIN之后可能是什么原因?

【问题讨论】:

  • 线程不按任何明确定义的顺序运行,它们彼此并行运行。因此,除非您同步它们的行为,否则线程将按什么顺序运行取决于操作系统,尽管有 pthread_yield() 调用。
  • sched_yield()(POSIX 标准)和pthread_yield()(非标准)的文档带有大量警告,说明它在某些实时调度程序情况下的使用方式以及在具有正常调度程序的进程没有很好地定义。它可能做你想做的事,但不做同样有效。

标签: c multithreading pthreads


【解决方案1】:

pthread_yield 是否可以/将会做您期望的事情(即让 HELPER 首先运行)取决于正在使用的系统调度程序及其配置方式。

一般而言,您只能在具有非常简单的调度程序的系统上期望(或者更确切地说希望)这种行为。现代 (Linux) 系统默认情况下会使用更复杂的调度,因此您不能依赖 pthread_yield 来同步执行顺序。

即使 MAIN 已停止并且 HELPER 已启动,HELPER 也可能在打印之前被抢占。或者多核 CPU 怎么样?如果两个线程并行运行会怎样?哪个会先打印?

所以 - 不,pthread_yield 不是同步线程的工具。

有关调度的更多信息,请阅读:

https://man7.org/linux/man-pages/man7/sched.7.html

您可以在此处阅读有关可用于获取有关调度程序的信息和配置调度程序的许多系统调用的信息。

但是为了控制线程执行顺序,你不应该依赖于控制调度器。实现您自己的控制,例如通过使用mutex

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-15
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多