c++ - 使用线程和互斥量时出现双重释放或损坏 (!prev) 错误

标签 c++ multithreading

我有简单的 C++ 代码,首先创建 4 个线程,然后将 1 发送 1000 次到 C++ 队列,然后是四个 0。这些线程中的每一个都尝试从该队列中读取,当任何线程读取 0 时,它终止并打印其本地总和。如果它读取 1,那么它只是将总和加 1。读数受互斥量保护。代码在 5 次中有 4 次按预期工作,但有时我会收到 double free or corruption (!prev) 错误... ...Abort core dumped。我还使用 gdb 调试了代码,但只得到 received signal SIGABRT, Aborted ... ...at raise.c: No such file or directory". 我没有明确分配或取消分配任何内存。可能导致问题的原因是什么?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue>

std::queue<int> my_queue;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *process(void *arg){
    int sum = 0;
    while(1){
        if(!my_queue.empty()){
            pthread_mutex_lock(&mutex);
            if (my_queue.front() == 1){
                sum += 1;
                my_queue.pop();
                pthread_mutex_unlock(&mutex);
            }
            else{
                my_queue.pop();
                printf("Sum: %d\n", sum);
                pthread_mutex_unlock(&mutex);
                break;
            }
        }
    }
    return arg;
}

int main(void){
    pthread_t id[4];
    for(int i = 0; i < 4; i++){
        if (pthread_create(&id[i], NULL, process, NULL) != 0){
            fprintf(stderr, "%s\n", "Error creating thread!");
            exit(EXIT_FAILURE);
        }
    }
    for (int i = 0; i < 1000; i++){
        my_queue.push(1);
    }
    for (int i = 0; i < 4; i++){
        my_queue.push(0);
    }
    for (int i = 0; i < 4; i++){
        pthread_join(id[i], NULL);
    }
    return EXIT_SUCCESS;
}

最佳答案

你有两个问题:

首先,您在不持有锁的情况下插入队列,其次,您在不持有锁的情况下测试队列是否为空。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue>

std::queue<int> my_queue;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *process(void *arg){
    int sum = 0;
    bool keep_going = true;
    while(keep_going){
        pthread_mutex_lock(&mutex);
        if(!my_queue.empty()){
            if (my_queue.front() == 1){
                sum += 1;
            }
            else{
                keep_going=false;
            }
        }
        my_queue.pop();
        pthread_mutex_unlock(&mutex);
    }
    printf("Sum: %d\n", sum); // Don't do IO while holding a lock!
    return arg;
}

int main(void){
    pthread_t id[4];
    // Initialize queue *before* creating threads.
    for (int i = 0; i < 1000; i++){
        my_queue.push(1);
    }
    for (int i = 0; i < 4; i++){
        my_queue.push(0);
    }
    // Create threads
    for(int i = 0; i < 4; i++){
        if (pthread_create(&id[i], NULL, process, NULL) != 0){
            fprintf(stderr, "%s\n", "Error creating thread!");
            exit(EXIT_FAILURE);
        }
    }
    // Join them.
    for (int i = 0; i < 4; i++){
        pthread_join(id[i], NULL);
    }
    return EXIT_SUCCESS;
}

如果你想在创建线程后添加到队列中,你需要这样的东西:

    pthread_mutex_lock(&mutex);
    my_queue.push(value);
    pthread_mutex_unlock(&mutex);

在 for 循环中。此外,在您到达零之前,队列很有可能会清空。要么通过等待信号量来正确地完成它,要么队列循环需要变成这样的:

        pthread_mutex_lock(&mutex);
        if(my_queue.empty()){
            pthread_mutex_unlock(&mutex);
            usleep(1);
            pthread_mutex_lock(&mutex);
        } else {

线程将在此处短暂休眠以使队列填满。

此外,您正在用 C++ 编写。学习编写一个 RAII 类来调用 pthread_mutex_lock 和解锁。

关于c++ - 使用线程和互斥量时出现双重释放或损坏 (!prev) 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44387584/

相关文章:

ios - 在同一数据库上同时使用核心数据和基于 sqlite c 的 api

c++ - 尝试设置唯一指针 bool 数组的值时出现 BAD_ACCESS 错误

java - 在线程上运行 GoogleApiClient 会导致错误

C++:如何使用 thread_local 声明指针变量?

c++ - 如何在与LUA脚本一起使用的Lambda中引用 'this'

java - Android 中的 java.util.Observable 是线程安全的吗?

Java - 多线程代码不会在更多内核上运行得更快

java - notifyAll() 不通知所有线程

c++ - 在 C++ 中调用线程两次时变量重叠

c++ - 封装:公共(public)成员与公共(public)方法