两个线程进入无限循环

Two threads entering in infinite loops

本文关键字:无限循环 线程 两个      更新时间:2023-10-16

我正在学习pthread概念。我为下面的问题写了一个代码:

实现以下模型:创建一个主线程。它打开一个文件。以随机的间隔,主线程创建工作线程随机间隔和每个工作线程将随机休眠从文件中读取一行并最终退出的时间间隔。

我写了以下代码:

#include<stdio.h>
#include<pthread.h>
char c;
void *f1(void *f)
{
    printf("Calling from thread 1n");
    sleep(rand()%2);
    while(c!='n'&& c!=EOF)
    {
        printf("1 %cn",c);
        c=getc(f);
    }
    pthread_exit(NULL);
}

void *f2(void *f)
{
    printf("Calling from thread 2n");
    sleep(rand()%2);
    while(c!='n' && c!=EOF)
    {
        printf("2 %cn",c);
        c=getc(f);
    }
    pthread_exit(NULL);
}
int main()
{
    pthread_t tid1,tid2;
    FILE *f;
    f=fopen("new.txt","r");
    int i;
    c=getc(f);
    while(c!=EOF)
    {
        i=rand()%2;
        sleep(i);
        pthread_create(&tid1,NULL,f1,(void *)f);
        i=rand()%2;
        sleep(i);
        pthread_create(&tid2,NULL,f2,(void *)f);
    }
    pthread_exit(NULL);
    return 0;
}

执行时,代码进入无限循环。有时只执行第一行,然后进入无限循环。甚至当我使用pthread_join时,问题也没有解决。为什么会进入无限循环?

以下是一些问题:

  • 你在main和两个线程中使用一个全局变量c。所以它们都覆盖了其他使用的值。
  • 您有一个几乎完全相同的代码副本作为线程运行:f1()f2()。相反,您可以使用一个由多个线程运行的函数f()。这是多线程的主要思想。
  • 可以使用pthread_self()打印线程ID。
  • pthread_exit()在函数返回时隐式调用。
  • main()没有作为线程显式启动,所以调用pthread_exit()没有意义。
  • 你缺乏沟通&线程之间的同步,告诉对方它们将读取哪一行。你应该使用"主"线程来跟踪,并让每个"工作"线程询问读取的位置。(我想说这是一个不平凡的任务。)

EDIT AFTER @Maksim Solovjov COMMENT

实际上问题是你只读一行,即直到'n'被击中。一旦任何线程读取了这个'n'字符,其他线程(或主while-loop)就不会再读取了。因此,它将永远卡在循环中。

那么,如果你像下面这样改变两个线程中的while循环,

while(c!=EOF)

线程将继续读取下一行。最后,流将到达EOF,线程可以退出。

修改后的线程代码将看起来像

void *f1(void *f)
{
    printf("Calling from thread 1n");
    sleep(rand()%2);
    while( c!=EOF)  //======>>>this is where change is required.
    {
        printf("1 %cn",c);
        c=getc((FILE *)f);
    }
    pthread_exit(NULL);
}

在第一个线程函数f1中,您正在编写

while(c!='n'&& c!=EOF)
    {
        printf("1 %cn",c);
        c=getc(f);
    }

然后返回到主函数和第二个线程。现在,c的值是'n'。因此在f2中,您将不会进入循环。因此,main中的while循环将永远继续下去,因为c的值没有改变,并且卡在'n'中。这就是产生无限循环的原因。因此,您还可以得出结论,您创建的线程没有进入任何无限循环。

解决方案:

一旦退出线程函数中的循环,就更改c的值。

if(c!=EOF)
   c = getc(f);

永远不会有"无限循环中的两个线程"。它是处于无限循环中的主线程。这是因为:你在两个不同线程调用的不同函数中读取文件,直到其中一个到达EOF或"n"。假设你的线程执行函数1达到"n",它将退出。但是现在主线程将进入无限循环,因为EOF将永远不会出现在两个函数检查while(c!='n'&&c!=EOF)进一步读取文件。

为了摆脱这种情况,您可以使用一个全局状态变量,它将处理"n"阻塞。

代码看起来像这样:

#include<stdio.h>
#include<pthread.h>
char c;
int isBlock;
void *f1(void *f)
{
    printf("Calling from thread 1n");
    sleep(rand()%2);
    while((c!='n' || isBlock) && c!=EOF)
    {
        isBlock = 0;
        printf("1 %cn",c);
        c=getc(f);
    }
    isBlock = 1;
    printf("exiting from thread 1n");
    pthread_exit(NULL);
}

void *f2(void *f)
{
    printf("Calling from thread 2n");
    sleep(rand()%2);
    while((c!='n'|| isBlock) && c!=EOF)
    {
        isBlock = 0;
        printf("2 %cn",c);
        c=getc(f);
    }
    isBlock = 1;
    printf("exiting from thread 2n");
    pthread_exit(NULL);
}
int main()
{
    pthread_t tid1,tid2;
    FILE *f;
    f=fopen("checkConnection.cpp","r");
    int i;
    c=getc(f);
    isBlock = 0;
    while(c!=EOF)
    {
        //c=getc(f);
        i=rand()%2;
        sleep(i);
        pthread_create(&tid1,NULL,f1,(void *)f);
        i=rand()%2;
        sleep(i);
        pthread_create(&tid2,NULL,f2,(void *)f);
}
    pthread_exit(NULL);
    return 0;
}