用于线程并发的 C 语言中的 Peterson 算法(段错误)



嘿伙计们,我正在用 C 语言实现 Peterson 的算法。我有两个函数将由创建的线程执行,一个将 1 加到变量,另一个将 1 减去同一变量。

程序接收一个 int 类型的参数,该整数是我要创建的线程数的平方根,例如,如果我在终端类型中执行它 ./算法 10,将创建 10*10 (10 000) 个线程。

如果 y 类型小于 170 作为参数(将创建 28900 个线程),程序运行正常,但如果我想创建更多线程,我遇到了段错误,尝试使用"long long int"变量,但事实并非如此。

有一个名为"cont"的计数器,每次cont达到10 000时都会打印变量。 变量的最后一个结果还有另一个打印,它应该始终为 0,因为 n 个线程加了 1,n 个线程减去了 1。

我想知道为什么我会遇到段错误,如果要创建的线程有限制,或者它是否是我的代码中的某些内容。

我使用下一个命令运行它以仅使用一个处理器,因为 Peterson 的算法仅在单处理器系统上完美运行:

taskset -c 0 ./alg3 100

代码如下:

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


long int n;
long int var = 0;
long int cont = 1;
int flag[] = {0, 0};
int turn = 0;
void* sum(void* data) {
//int n = *((int*)data); 
int i;
turn = 2;
flag[0] = 1;
while (turn == 2 && flag[1]);
cont++;
var += 1;
if (cont == 10000) {
printf("varsum=%ldn", var);
cont = 1;
}
flag[0] = 0;
}
void* rest(void* data) {
//int n = *((int*)data); 
int i;
turn = 1;
flag[1] = 1;
while (turn == 1 && flag[0]);
cont++;
var -= 1;
if (cont == 10000) {
printf("varres=%ldn", var);
cont = 1;
}
flag[1] = 0;
}
main(int argc, char *argv[]) {
long int i;
n = atoi(argv[1]);
n *= n; //n*n is the actual number of threads that will be created
pthread_t tid[n];

for (i = 0; i < n; i++) {
pthread_create(&tid[i], NULL, sum, NULL);
//cont++;
}
for (i = 0; i < n; i++)
pthread_join(tid[i], NULL);
for (i = 0; i < n; i++) {
pthread_create(&tid[i], NULL, rest, NULL);
//cont++;
}
for (i = 0; i < n; i++)
pthread_join(tid[i], NULL);
printf("main() reporting that all %ld threads have terminatedn", i);
printf("variable=%ldn", var);
} /* main */

首先,创建线程当然是有限制的。它由每个线程和硬件的堆栈大小决定,细节建议谷歌它...... 分段故障原因: 您没有检查函数 pthread_create 的返回值,当 'n' ls 足够大时,pthread_create 将失败,那么pthread_join可能会使用不存在的 thread_t 作为第一个输入参数。以下代码(与示例不同)可以测试可以创建多少个线程。

int rc = 0, thread_num = 0;
for (i = 0; i < n; i++) {
rc = pthread_create(&tid[i], NULL, sum, NULL);
if (rc)
{
printf("pthread_crate failed, thread number: %d, error code: %dn", thread_num, rc);
}
thread_num++;
}
printf("created %d threads.n", thread_num);

至少在pthread_create()中添加错误检查以避免将无效的pthread_t变量传递给pthread_join()

int main(int arc, char ** argv)
{
...
pthread_t tid[n];
int result[n];

for (i = 0; i < n; i++) {
result[i] = errno = pthread_create(&tid[i], NULL, sum, NULL);
if (0 != errno) {
perror("pthread_create() failed");
}
}
for (i = 0; i < n; i++) {
if (0 == result(i]) {
errno = pthread_join(tid[i], NULL);
if (0 != errno) {
perror("pthread_join() failed");
}
}
}
...

还要始终保护对写入变量的并发访问,count此处。为此,请使用pthread_mutex_t变量。

最新更新