【问题标题】:C++ Multithreading exception when not calling Thread.join()不调用 Thread.join() 时的 C++ 多线程异常
【发布时间】:2016-06-24 02:01:47
【问题描述】:

我有一个非常简单的程序,它给了我一个我不理解的异常。我有一个用 Visual Studio Express 2012 for Desktop 编写的 C++ 应用程序。

我创建了一个多线程应用程序,其中有 2 个线程,一个调用一个人类,另一个调用另一个汽车类。

当我使用 thread.join() 时,我没有得到异常,但我没有得到所需的输出。当我注释掉 thread.join() 时,我得到了异常,但我也得到了所需的输出。

例外情况是: enter image description here

我只是想让两个线程同时执行和处理。人和汽车类都调用了一个方法,该方法在线程睡眠时重复 10 次,它所做的只是为人员类打印一个字符串“开始行走”,为汽车类打印一个字符串“开始驾驶”,而主线程只有“主要等待...”

所以程序的输出是:

started walking
started driving
started walking
started driving
main waiting...
started walking
started driving
started walking
started driving
main waiting...

等等。这就是我想要的。

如果我取消注释加入方法,我会得到以下输出:

started walking
started walking
(repeat 8 more times)
started driving 
started driving
(repeat 8 more times)
Main waiting..
Main waiting..
(repeat 8 more times)

这不是我想要的。

如果不使用 join() 方法,我怎样才能让这个应用程序在没有异常的情况下执行?

作为一个仅供参考,这是我在下面创建的示例代码:

这是启动程序的主要方法。

include <iostream>
#include <thread>
#include <chrono>
#include "person.h"
#include "car.h"

int count1 = 0;
int count2 = 0;

int main()
{
    person p1;
    thread t1(&person::startWalking, p1);
    if(t1.joinable())
    {
        //t1.join();
    }

    car c1;
    thread t2(&car::startDriving, c1);
    if(t2.joinable())
    {
        //t2.join();
    }

    for(int x = 0; x < 10; x++)
    {
        std::cout<<"Main waiting...\n";//<<std::endl;
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    return 0;
}

这是 person.cpp 文件:

#include "person.h"
person::person(void)
{
}
person::~person(void)
{
}
void person::startWalking()
{
    for(int x = 0; x < 10; x++)
    {
        cout<<"Started Walking.\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

void person::stopWalking()
{
    cout<<"Stopped Walking.\n";
}

这是 car.cpp 文件:

#include "car.h"

using namespace std;

car::car(void)
{
}
car::~car(void)
{
}
void car::startDriving()
{
    for(int x = 0; x< 10; x++)
    {
        std::cout<<"started driving\n.";
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

【问题讨论】:

  • 阅读std::thread::join的文档。
  • 我有,但并没有真正说明什么会导致我粘贴的异常。站点 cplusplus.com/reference/thread/thread/join 提到调用 join() 方法“这会阻止调用此函数的线程的执行,直到构造调用的函数返回(如果尚未返回)。”问题是我不希望被调用的线程阻塞调用它的线程。我希望它们同时运行,但我得到了这个异常。
  • 我必须承认我现在有点不好意思。我在网上查看,看到调用 thread.detach() 方法给了我想要的输出,它也没有给出异常。在发布这个问题之前,我责怪自己在网上看起来不够好。
  • 异常文本不要使用图片,这样会导致无法搜索。哦,搜索该文本,它可能会揭示出什么问题以及在文档中的何处可以找到有关它的信息。最后,将您的代码缩减为一个最小但完整的示例;没有它,根据定义,它是题外话。
  • std::thread::detach 不是正确的解决方案。当你用线程编程时,修改代码直到它看起来可以工作是绝对错误的方法。您需要加入两个线程,但要等到它们被启动。一旦你这样做了,你就不需要睡眠电话了。而且您不需要检查新启动的线程是否可连接。是的。

标签: c++ multithreading exception join


【解决方案1】:

首先,document 读取 If the thread is joinable when destroyed, terminate() is called.,所以如果你注释 thread.join() 并且 main 函数完成,线程必须调用析构函数,它会调用 terminate 和 @ 987654326@ 在这里是abort,所以你有一个例外!

如果你取消注释 thread.join(), join 方法 returns when the thread execution has completed. 所以你不能得到例外的答案。

建议:

移动

if(t1.joinable())
{
    t1.join();
}

if(t2.joinable())
{
    t2.join();
}

std::this_thread::sleep_for(std::chrono::milliseconds(5000)); 之前。您可以看到这三个线程同时执行,但您也无法获得您想要的结果,因为t1t2 睡眠1 秒,所以主线程会很快打印Main waiting...。所以你应该在 t1t2 中注释 sleep 或者在 main 的 for 中为每个循环添加相同的睡眠时间。

提示:这三个线程会竞争,输出缓冲区会随机填充,所以输出是不可预测的,你可以添加一个互斥体来保证输出可读。

这是我的参考代码:

#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>

std::mutex mMutex;

class person {
public:
    void startWalking()
    {
        for(int x = 0; x < 10; x++)
        {
            mMutex.lock();
            std::cout<< "Started Walking.\n";
            mMutex.unlock();
            //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }
};

class car {
public:
    void startDriving()
    {
        for(int x = 0; x< 10; x++)
        {
            mMutex.lock();
            std::cout <<"Started driving.\n";
            mMutex.unlock();
            //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }
};

int main()
{
    person p1;
    std::thread t1(&person::startWalking, p1);

    car c1;
    std::thread t2(&car::startDriving, c1);

    for(int x = 0; x < 10; x++)
    {
        mMutex.lock();
        std::cout <<"Main waiting...\n";
        mMutex.unlock();
        //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
    t1.join();
    t2.join();
    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 2011-12-16
    相关资源
    最近更新 更多