【问题标题】:Detached Threads: mutex destroyed while busy Error C++分离的线程:忙时互斥体被破坏错误C++
【发布时间】:2020-01-25 13:31:17
【问题描述】:

我完全是 C++ 和线程的初学者。我为我的问题做了一个非常简单的例子。在我提供的代码中,我创建线程并分离它们。每个线程执行不同的函数:一个包括将 int 推入队列,另一个读取该值并使用读取的值和函数的参数模拟长时间处理。队列对象受互斥体保护,因为它在两个线程之间共享。我知道我的代码有点愚蠢,但我已经让它代表了我真正的问题,它使用分离的线程和受互斥体保护的共享队列。

代码如下:

#include <mutex>
#include <iostream>
#include <thread>
#include <queue>    
using namespace std;      

std::queue<int> tasks;
std::mutex m; 

void push_task(int arg) {

    printf("[Pushing task into the queue]");

    m.lock();
    tasks.push(arg);
    m.unlock();

}

void process_task(int number) {

    printf("[Processing task from the queue]");

    m.lock();

    while (tasks.empty() == false){

        int task = tasks.front(); 
        tasks.pop(); 
        printf("[Processing...]");
        std::this_thread::sleep_for(std::chrono::milliseconds((task+number)*1000)); //simulate some execution
        printf("[Task has been successfully processed]");
    }

    m.unlock(); 
}

int launch_threads(int nTask, int n){

    int counter = 0;

    while(counter < 8){
        std::thread(push_task, nTask).detach();
        std::thread(process_task, n).detach();
        counter++;
    }

    printf("[Launch Threads Ends]");

    return 0;
}

int main(){

   launch_threads(0, 10000);

    printf("[Main Ends]");

    return 0;

}

好吧,我面临的问题是我收到以下错误:

mutex 在忙时被破坏

我已经调查并且我已经阅读(如果我错了,请纠正我)发生这种情况是因为调用函数(在我的例子中是 launch_threads())在它内部创建的本地线程仍在运行时结束,因此互斥锁仍然可以由某个线程拥有(正忙),给出该错误。事实上,线程内部的处理并没有真正结束。

我的问题是:我怎样才能避免这个错误?

我还读到不将线程作为局部变量可能会解决问题。在这种情况下,如果我将带有参数的函数传递给线程,如何将线程声明为全局线程?

与主题相关的额外问题:使用 std::lock_guard lock(m) 是否有助于避免该问题?

提前谢谢你!

【问题讨论】:

标签: c++ multithreading mutex


【解决方案1】:

您启动一些线程并将它们分离。然后让main 函数返回终止进程。该进程终止会杀死所有线程并导致所有全局对象被破坏。

您应该只退出正在运行main 函数的线程,这样可以让分离的线程继续在进程中运行(然后在最后一个线程退出时退出)。 p>

目前在 C++ 标准库中没有办法退出线程,所以你必须使用系统相关的函数。例如,在 POSIX 系统(如 Linux 或 macOS)中,您使用 pthread_exit 函数。


当然还有另外两种可能的解决方案:

  1. 在退出 main 之前不要分离线程和 join。不过,这可能并不总是可行或不希望发生的。

  2. main 函数内等待分离的线程退出,使用线程已退出的其他类型的等待或轮询机制。这也可能不是所希望的。如果线程在线程内部设置main 函数检查的标志,则可能会出现问题,这可能会导致在main 函数返回之前线程实际上还没有退出的竞争条件。

【讨论】:

  • 谢谢,非常感谢
  • Re,“你应该做 X...没有标准的方法来做 X,所以你必须使用系统相关的函数。”如果执行 X 是解决某些问题的唯一方法,这可能是一个很好的建议,但这里并非如此。 OP 不需要需要主线程在其他线程之前终止。如果 OP 重新编写程序以便主线程将 join() 它创建的线程,该程序也可以正常工作。
  • @SolomonSlow 除了无法加入分离的线程。并且有很多用例,即使主线程退出,也可能希望分离的线程继续工作。
  • 抱歉,我认为众所周知,C++ 程序必须在每个std::thread t精确地调用t.detach()t.join()。不好的假设。我想应该说,“如果 OP 重新编写程序,以便主线程将 join() 它创建的每个线程 而不是 detach() 分离它们,该程序也可以正常工作。 i>"
【解决方案2】:

你的主要功能结束了——你的整个程序也结束了。任何其他线程都无法阻止这一点 - 因此您必须等待它们完成(参见 std::thread::join)。这可能就是你所需要的。 但是互斥锁是怎么回事?所有程序资源在程序结束时都被销毁 - 你不能销毁繁忙的互斥锁(见 std::lock_guard)

更新:注意到另一件坏事——你没有同步线程——所以生产/消费线程会有数据竞争,并且不能保证你的所有数据都得到处理。

【讨论】:

    猜你喜欢
    • 2015-04-16
    • 1970-01-01
    • 2018-04-22
    • 1970-01-01
    • 2021-11-07
    • 2021-08-20
    • 1970-01-01
    • 2020-03-23
    • 2023-03-26
    相关资源
    最近更新 更多