多线程中的输出不明确

时间:2019-04-21 18:34:18

标签: c++ multithreading

我的代码生成的输出是不明确的。

int main()
{

    cout << "THIS IS AN THREADING EXAMPLE IN C++" << endl;
    cout<<"MAIN , reverse and forward are executed"<<endl;
    thread rev_thread(print_reverse,1);
    thread for_thread(print_forwward,1);
    rev_thread.join();
    for_thread.join();
    cout << "AIN , reverse and forward are DONE" << endl;
    return 0;
}
    void print_reverse(int wait_sec)
    {
       for(int rev=5000;rev>=1;rev--)
    {
    //std::this_thread::sleep_for (std::chrono::seconds(wait_sec));
     cout<<"The rev ::" << rev<<endl;

    }
    }
void print_forwward(int wait_sec)
{
    for(int forw=1;forw<=5000;forw++)
    {
    //std::this_thread::sleep_for (std::chrono::seconds(wait_sec));
    cout<<"The forward ::" << forw<<endl;

    }
}
  
    

我期望以任意随机方式混合使用print_forwward和print_reverse **

  

但这就是我得到的:-
转速:: 4997

转速:: 4996
转速:: 4995
转速:: 4994
转速:: 4993
转速:: 4992
转速:: 4991
转速:: 4990
转速:: 4989
转速:: 4988
转速:: 4987
转速:: 4986

前锋:: 2
前进:: 3
前进:: 4
前进:: 5
前进:: 6
前进:: 7
前进:: 8
转速:: 4985
转速:: 4984
转速:: 4983
转速:: 4982
转速:: 4981
前进::放牧:: 4980
转速:: 4979
9转速:: 4978
转速:: 4977
转速:: 4976

前锋:: 10
前进:: 11
前进:: 12
前进:: 13
前进:: 14
转速::前进:: 15
前进:: 16
4975前进:: 17
前进:: 18
前进:: 19
前进:: 20
前进:: 21
前进:: 22

转速::前锋:: 234974
前进:: 24
前锋:: 25

234974到底是什么?而且打印版本可以单行前进? 请注意,间隙也以与输出相同的方式打印!
我在这里注释了等待测试的内容
请注意,我是这个概念的新手。
任何帮助将不胜感激

2 个答案:

答案 0 :(得分:2)

用于流的C ++运算符<<并非“线程安全”;意思是说,没有什么能阻止控件在std::cout << x << y;的输出和x的输出之间的类似y的表达式中间的线程之间进行切换。

您看到的是23紧随其后的4974

不幸的是,由于操作员定义了令人讨厌的接口,使其变得“线程安全”也不是一件容易的事(不是不可能,但是很烦人)。

实际上,字符串格式方法la printf对此也更好。

答案 1 :(得分:1)

  

234974到底是什么?以及打印版本和前进   一条线??!!请注意,间隙也以相同的方式打印   作为输出!在这里,我已注释掉等待测试的内容,请注意   我是这个概念的新手。任何帮助将不胜感激


对我来说很明显,您的输出“混合” 发生了,只是比您预期的更有趣或与众不同。我发现这种“中断” /“交错”输出(在串行设备上)甚至在实时操作系统中也是如此。

  

我期望print_forwward和print_reverse任意混合   方式**

合理。但是您尚未确定正在运行的操作系统,也未确定有多少个活动的内核都可以促进或改变您的结果。

我认为可以通过使用互斥量来容忍(cout缺乏线程安全性)问题,这样一次只能有1个线程可以退出。

最简单的重构可能是在每个cout之后(在for循环中)在前面的互斥锁()和解锁()。


您可以考虑将cout-of-a值替换为大向量中的push-of-a值。是的,向量也需要互斥访问,但是由于基于内存,推送应该比cout快得多。 (对不起,我还没测量。)

在我的实验中,10个(默认)线程(在2核心硬件上)将值推入向量(初始值为5000万的初始值),持续10秒。完成填充向量的“竞赛”后,一个线程将向量内容引出到文件中以供以后分析(最新测试内容约为3,700万个字符。简要报告说,该代码花费了大约3秒钟的时间来编写向量内容转换为文本文件。)

writing ID sequence of 31,862,791 values to ./Q6.txt
complete: 2,968,610 us

(任意)10秒持续时间是通过线程主线程在10个线程运行时几乎不执行任何操作来测量的。以下代码段用于线程的启动和连接之间,并且还会产生一个“进度cout”(因为其他线程不使用cout)

// threads start

// progress indicator to user
for (size_t i = 0; i < MaxSecs; ++i) // let threads switch for 10 seconds
{
    sleepToWallClockStartOfSec();    // 'main()' sync's to wall clock
    cout << (MaxSecs-i-1) << ' ' << flush; // "9 8 7 6 5 4 3 2 1 0"
}
m_done = true;  // command threads to exit - all threads can see m_done

// threads joins

Linux使我感到惊讶……完成了很少的上下文切换。