我正在学习pthread的概念。我为以下问题编写了一个代码:
实现以下模型:创建主线程。它开了一个 文件。在任意间隔,主线程创建工作线程 随机间隔和每个工作线程将随机休眠 在从文件中读取一行并最终退出之前的间隔。
我写了以下代码:
#include<stdio.h>
#include<pthread.h>
char c;
void *f1(void *f)
{
printf("Calling from thread 1\n");
sleep(rand()%2);
while(c!='\n'&& c!=EOF)
{
printf("1 %c\n",c);
c=getc(f);
}
pthread_exit(NULL);
}
void *f2(void *f)
{
printf("Calling from thread 2\n");
sleep(rand()%2);
while(c!='\n' && c!=EOF)
{
printf("2 %c\n",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
,问题仍未解决。
为什么它会进入无限循环?
答案 0 :(得分:4)
以下是一些问题:
c
和两个主题中使用了一个全局变量main
。所以他们都覆盖了其他人使用的价值。f1()
和f2()
。相反,您可以拥有一个由多个线程运行的函数f()
。这是多线程的主要思想。pthread_self()
打印主题ID。pthread_exit()
会被隐式调用。main()
未明确地作为线程启动,因此调用pthread_exit()
没有意义。答案 1 :(得分:2)
编辑@Maksim Solovjov后的评论
实际上问题是你只读了一行,即直到'\n'
被击中。一旦任何线程读取此'\n'
字符,就不会再读取其他线程(或主while循环)。因此它将永远陷入循环。
因此,如果您在以下两个线程中更改while循环,
while(c!=EOF)
线程将继续并读取下一行。最后,流量将达到EOF,线程可以退出。
修改线程后代码看起来像
void *f1(void *f)
{
printf("Calling from thread 1\n");
sleep(rand()%2);
while( c!=EOF) //======>>>this is where change is required.
{
printf("1 %c\n",c);
c=getc((FILE *)f);
}
pthread_exit(NULL);
}
答案 2 :(得分:2)
在第1个线程函数f1中,您正在编写
while(c!='\n'&& c!=EOF)
{
printf("1 %c\n",c);
c=getc(f);
}
然后你回到主函数和第二个线程。所以现在,c的值是'\n'
。因此在f2中,您将不会进入循环。因此,main中的while循环将永远持续,因为c的值不会改变并且卡在'\n'
中。这是获得无限循环的原因。因此,您还可以得出结论,您创建的线程没有进入任何无限循环。
解决方案:
一旦退出线程函数中的循环,请更改c。
的值if(c!=EOF)
c = getc(f);
答案 3 :(得分:1)
在无限循环中永远不会有两个线程&#34;。它是inifinite循环中的主要线程。发生这种情况是因为: 您正在读取由不同线程调用的两个不同函数中的文件,直到其中一个达到EOF或&#34; \ n&#34;。 假设你的线程执行函数到达&#34; \ n&#34;它会退出。但是现在主线程将进入无限循环,因为EOF永远不会同时检查函数(c!=&#39; \ n&#39;&amp;&amp; c!= EOF)以进一步读取文件。
为了摆脱这种情况,你可以使用一个全局状态变量,它将负责&#34; \ n&#34;阻塞。
代码将如下所示:
#include<stdio.h>
#include<pthread.h>
char c;
int isBlock;
void *f1(void *f)
{
printf("Calling from thread 1\n");
sleep(rand()%2);
while((c!='\n' || isBlock) && c!=EOF)
{
isBlock = 0;
printf("1 %c\n",c);
c=getc(f);
}
isBlock = 1;
printf("exiting from thread 1\n");
pthread_exit(NULL);
}
void *f2(void *f)
{
printf("Calling from thread 2\n");
sleep(rand()%2);
while((c!='\n'|| isBlock) && c!=EOF)
{
isBlock = 0;
printf("2 %c\n",c);
c=getc(f);
}
isBlock = 1;
printf("exiting from thread 2\n");
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;
}