【发布时间】:2021-08-08 12:50:29
【问题描述】:
我正在尝试创建 1000000 多个线程并让它们从队列中添加和删除元素。 队列的大小为 10 个元素,当它已满并想要添加一个元素时,它会等待来自 Condition 的信号,当它为空并尝试删除元素时也是如此。
当我创建 100000 个线程时,代码运行良好,但是当我尝试添加一个或多个零时,它给了我一个分段错误。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define SIZE 10
long NBTHREADS = 1000000;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t notFull = PTHREAD_COND_INITIALIZER;
pthread_cond_t notEmpty = PTHREAD_COND_INITIALIZER;
long sum = 0;
typedef long element;
typedef struct queue{
element data[SIZE];
int front, rear;
}queue;
queue CreateQueue(){
queue q;
q.front = 1;
q.rear = 0;
return q;
}
queue list;
int isEmptyQueue(queue q) {
return (q.front == (q.rear + 1) % SIZE);
}
int isFullQueue(queue q) {
return (q.front == (q.rear + 2) % SIZE);
}
int EnQueue(queue *q,element e) {
q->rear = (q->rear + 1) % SIZE;
q->data[q->rear] = e;
return 1;
}
int DeQueue(queue *q) {
q->front = (q->front + 1) % SIZE;
return 1;
}
int Front(queue q,element *e) {
if (isEmptyQueue(q))return 0;
*e = q.data[q.front];
return 1;
}
void PrintQueue(queue q){
element e;
while(!isEmptyQueue(q) && Front(q, &e)){
printf("%ld ", e);
DeQueue(&q);
}
printf("\n");
}
void *addToList(void *num)
{
long number = (long)num;
pthread_mutex_lock(&lock);
while(isFullQueue(list))
pthread_cond_wait(¬Full, &lock);
EnQueue(&list, number);
pthread_cond_signal(¬Empty);
sum++;
pthread_mutex_unlock(&lock);
pthread_exit(0);
}
void *deleteFromList()
{
pthread_mutex_lock(&lock);
while(isEmptyQueue(list))
pthread_cond_wait(¬Empty, &lock);
DeQueue(&list);
pthread_cond_signal(¬Full);
sum++;
pthread_mutex_unlock(&lock);
pthread_exit(0);
}
int main()
{
list = CreateQueue();
void *status;
pthread_attr_t attr;
pthread_t threads[NBTHREADS];
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(long i=0; i<NBTHREADS; i++)
{
long err;
if(i<(NBTHREADS/2))
{
err = pthread_create(&threads[i], &attr, addToList, (void*)i);
}else{
err = pthread_create(&threads[i], &attr, deleteFromList, NULL);
}
if(err){
printf("\nError Creating Thread...");
exit(-1);
}
}
pthread_attr_destroy(&attr);
for(long i=0; i<NBTHREADS; i++)
{
long err = pthread_join(threads[i], &status);
if(err)
printf("\nFAILED TO JOIN MAIN WITH THREAD %ld", (long)status);
else
printf("\nsuccessfully joined");
}
printf("\nSum is: %ld", sum);
PrintQueue(list);
pthread_exit(NULL);
}
它给了我这个错误:
Process returned -1073741571 (0xC00000FD) execution time : 9.364 s
我还是多线程和并行编程的新手。
也许我在错误的地方使用了锁?
但问题是,当我将 NBTHREADS 变量设置为 100000 或更少时,程序执行良好并返回 0,并且队列没有打印任何内容(它是空的)。
我不知道我的问题出在哪里,感谢您的帮助。
【问题讨论】:
-
那是……很多线程。可能超出您的系统支持的范围。
-
或者你的
threads数组变得太大导致堆栈溢出。 -
在 C 中,您不应该将大数组作为“局部变量”。所以不要这样做:
pthread_t threads[NBTHREADS];要么将其作为(丑陋的)全局变量,要么使用malloc分配它 -
我的两分钱,您的
queue CreateQueue()方法在其堆栈上创建一个queue结构并返回它以初始化您的list静态queue结构。一种更有效的方法是将list上的指针传递给CreateQueue并让它直接初始化您的静态list(或直接使用静态结构方法对其进行初始化),此处堆栈上的数据交换似乎没有用,因为你list对象已经有它的保留空间。作为参考,在 x86 上,gcc 的常见堆栈限制接近 100 万个指针,这应该可以解释您的实际问题。 -
@KamelYehya 答案已更新为代码示例。试试看,如果有帮助,请告诉我们
标签: c multithreading parallel-processing segmentation-fault pthreads