我有简单的 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/