在linux CFS调度下的C/ c++多线程场景中出现意外结果
Unexpected result in multithreading scenario in C/C++ under linux CFS schedualar
我在主线程内创建了多个线程(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线程第二次获得CPU
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线程在CFS调度其他线程之前第二次意外获得CPU
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->Time Now: 00:17:45.362716000
foo1-->2-->Time Now: 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() <<"nn";
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;
}
这里是完全公平调度细节
内核。Sched_min_granularity_ns = 100000内核。Sched_wakeup_granularity_ns = 25000 kernel。sched_latency_ns =1000000
根据sched_min_granularity_ns值,任何任务都将在该最小时间内执行,如果任务需要的时间超过该最小时间,则计算时间片,并在该时间片内执行每个任务。
这里时间片是用公式计算的,
time slice =(每个任务的权重/下所有任务的总权重)CFS运行队列x sched_latency_ns
谁能解释为什么我得到这些结果调度????任何帮助理解输出将是非常感激的。提前谢谢你。
我在linux下使用gcc。
EDIT:
如果我改变这个循环
(int k = 0; k<100000; k + +);
到
(int k = 0; k<10000; k + +);
则有时线程1连续获得CPU 10次,线程2连续获得CPU 5次,线程3连续获得CPU 5次,主线程连续获得CPU 2次,线程4连续获得CPU 7次。看起来不同的线程是随机被抢占的。
这些随机的没有连续的CPU分配给不同的线程的线索。
CPU分配一些时间来执行每个线程。为什么每个线程不做相同数量的打印?
我将在一个示例中解释这一点:
承认你的计算机每秒钟能发出100条指令承认打印1张相当于使用了25条指令承认每个线程有1ns的工作时间
现在你必须明白计算机中的所有程序都在消耗100条可用指令
如果你的线程想要打印一些东西,有100条指令可用,它可以打印4句话。如果你的线程想要打印一些东西,有40条指令可用,它可以打印1句。只有40条指令,因为其他程序正在使用指令。
你明白吗?
如果你有任何问题,欢迎提问。:)
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 使用++运算符会导致意外的结果
- 尝试将字符串/字符转换为整数会产生意外结果
- lower_bound() 给出意外的结果
- 三元运算符在返回语句中给出意外的结果
- RapidXML - 代码创建意外结果
- 类中静态函数C++意外结果
- 模板函数意外的结果
- 指针数组中的意外结果
- 使用指针访问数组元素时出现意外结果
- 使用 sprintf 和 %g 将双精度转换为字符串的意外结果
- C++:比较运算符>和字符串文本的意外结果
- 具有意外结果的 C++ 闭包
- 操作员!! 产生意外的结果
- yaml-cpp 比较的意外结果
- Spirit X3:自定义数字解析器在结果中产生意外的前导零
- 每次都出现意外结果
- 在 Qt 中解析嵌套的 JSON 时出现意外结果(数组不存在)
- 如何避免 std::abs 的意外结果?
- 声明双重给它一个值0,但打印结果意外变化