c++ - linux CFS schedualar下C/C++多线程场景出现意外结果

标签 c++ linux multithreading pthreads posix

我在主线程内创建了多个线程(4个线程)。虽然每个线程执行相同的功能, 线程的调度与预期的不一样。根据我对操作系统的理解,linux CFS 调度程序将 分配“t”虚拟运行时间量,并且在该时间量到期时,CPU 被当前线程抢占, 分配给下一个线程。通过这种方式,每个线程都将获得公平的 CPU 份额。我得到的并不符合预期。

我期望所有线程(线程 1-4、主线程)都会在同一线程(任何)下次获得 CPU 之前获得 CPU。

预期输出为

foo3-->1--->Time Now : 00:17:45.346225000

foo3-->1--->Time Now : 00:17:45.348818000

foo4-->1--->Time Now : 00:17:45.350216000

foo4-->1--->Time Now : 00:17:45.352800000

main is running ---> 1--->Time Now : 00:17:45.355803000

main is running ---> 1--->Time Now : 00:17:45.360606000

foo2-->1--->Time Now : 00:17:45.345305000

foo2-->1--->Time Now : 00:17:45.361666000

foo1-->1--->Time Now : 00:17:45.354203000

foo1-->1--->Time Now : 00:17:45.362696000

foo1-->2--->Time Now : 00:17:45.362716000 // foo1 thread got CPU 2nd time as expected

foo1-->2--->Time Now : 00:17:45.365306000

但是我得到

foo3-->1--->Time Now : 00:17:45.346225000

foo3-->1--->Time Now : 00:17:45.348818000

foo4-->1--->Time Now : 00:17:45.350216000

foo4-->1--->Time Now : 00:17:45.352800000

main is running ---> 1--->Time Now : 00:17:45.355803000

main is running ---> 1--->Time Now : 00:17:45.360606000

foo3-->2--->Time Now : 00:17:45.345305000 // // foo3 thread got CPU 2nd time UNEXPECTEDLY before scheduling other threads as per CFS

foo3-->2--->Time Now : 00:17:45.361666000

foo1-->1--->Time Now : 00:17:45.354203000

foo1-->1--->Time Now : 00:17:45.362696000

foo1-->2--->现在时间:00:17:45.362716000

foo1-->2--->现在时间:00:17:45.365306000

这是我的程序(thread_multi.cpp)

#include <pthread.h>
#include <stdio.h>
#include "boost/date_time/posix_time/posix_time.hpp"
#include <iostream>
#include <cstdlib>
#include <fstream>
#define NUM_THREADS  4

using namespace std;

std::string now_str()
{
    // Get current time from the clock, using microseconds resolution
    const boost::posix_time::ptime now = 
        boost::posix_time::microsec_clock::local_time();

    // Get the time offset in current day
    const boost::posix_time::time_duration td = now.time_of_day();
    const long hours        = td.hours();
    const long minutes      = td.minutes();
    const long seconds      = td.seconds();


    const long nanoseconds = td.total_nanoseconds() - ((hours * 3600 + minutes * 60 + seconds) * 1000000000);
    char buf[40];

    sprintf(buf, "Time Now : %02ld:%02ld:%02ld.%03ld", hours, minutes, seconds, nanoseconds);
    return buf;
}


/* This is our thread function.  It is like main(), but for a thread*/
void *threadFunc(void *arg)
{
    char *str;
    int i = 0;

    str=(char*)arg;

    while(i < 100 )
    {

        ++i;
        ofstream myfile ("example.txt", ios::out | ios::app | ios::binary);

        if (myfile.is_open())
          {
            myfile << str <<"-->"<<i<<"--->" <<now_str() <<" \n";

          }
          else cout << "Unable to open file";
        // generate delay 
        for(volatile int k=0;k<1000000;k++);



        if (myfile.is_open())
          {
            myfile << str <<"-->"<<i<<"--->" <<now_str() <<"\n\n";
            myfile.close();
          }
          else cout << "Unable to open file";
    }


}

int main(void)
{
    pthread_t pth[NUM_THREADS]; // this is our thread identifier
    int i = 0;

    pthread_create(&pth[0],NULL, threadFunc,  (void *) "foo1");
    pthread_create(&pth[1],NULL,  threadFunc, (void *) "foo2");
    pthread_create(&pth[2],NULL, threadFunc,  (void *) "foo3");
    pthread_create(&pth[3],NULL,  threadFunc, (void *) "foo4");



std::cout <<".............\n" <<now_str() << '\n';      

    while(i < 100)
    {

        for(int k=0;k<1000000;k++);

        ofstream myfile ("example.txt", ios::out | ios::app | ios::binary);
          if (myfile.is_open())
          {
            myfile << "main is running ---> "<< i <<"--->"<<now_str() <<'\n';
            myfile.close();
          }
          else cout << "Unable to open file";


        ++i;
    }

//  printf("main waiting for thread to terminate...\n");
    for(int k=0;k<4;k++)
    pthread_join(pth[k],NULL);

std::cout <<".............\n" <<now_str() << '\n';      
    return 0;
}

这是完全公平的调度程序详细信息

kernel.sched_min_granularity_ns = 100000 kernel.sched_wakeup_granularity_ns = 25000 kernel.sched_latency_ns = 1000000

根据 sched_min_capsularity_ns 值,任何任务都将在该最短时间内执行,如果任务需要超过该最短时间,则计算时间片,并且每个任务都将在该时间片内执行。

这里时间片的计算使用公式,

time slice = ( weight of each task / total weight of all tasks under that CFS run-queue ) x sched_latency_ns

谁能解释一下为什么我会得到这些调度结果??? 任何有助于理解输出的帮助都将受到高度赞赏。 预先感谢您。

我在linux下使用gcc。

编辑1:

如果我改变这个循环

for(int k=0;k<100000;k++);

进入

for(int k=0;k<10000;k++);

然后有时线程1连续10次获得CPU,线程2连续5次获得CPU,线程3连续5次获得CPU,主线程连续2次获得CPU,线程4连续7次获得CPU。看起来不同的线程在随机时间被抢占。

关于这些随机的连续 CPU 分配给不同线程的次数有什么线索吗??

最佳答案

CPU分配一些时间来执行每个线程。为什么每个线程的打印数量不同?

我将在一个例子中解释这一点:

承认你的计算机可以在 ns 内发出 100 条指令 承认打印 1 次相当于使用 25 条指令 承认每个线程有1ns的工作时间

现在您必须了解计算机中的所有程序都在消耗 100 条可用指令

如果当你的线程想要打印一些东西时,有 100 条可用指令,它可以打印 4 个句子。 如果当你的线程想要打印一些东西时,有 40 条可用指令,它可以打印 1 个句子。由于其他程序正在使用指令,因此只有 40 条指令。

你明白了吗?

如果您有任何疑问,欢迎您。 :)

关于c++ - linux CFS schedualar下C/C++多线程场景出现意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22488853/

相关文章:

c++ - 在 Codeblocks 中构建时出现 MinGW 的 ar.exe "could not create temporary file whilst writing archive: no more archived files"错误

c++ - 迷宫生成 - 递归除法(它是如何工作的?)

c++ - 模板继承的问题

c++ - 使用 C++ 查找 RAM 数量

multithreading - SDL-Mixer 音频在启动 Reactive-Banana 输入循环时停止

c++ - 为什么我的 OpenGL 纹理不起作用?

node.js 中的 Python-Shell 未在 Systemd 服务中运行

linux - 在 bashrc 中使用 linux "tee"命令

python - 如何在多线程或多处理中运行脚本

java - Java线程中的System.exit