C语言中的多线程死锁

C语言中的多线程死锁,c,multithreading,pthreads,deadlock,C,Multithreading,Pthreads,Deadlock,我是C新手,有以下多线程场景,其中N个线程从单个二进制文件读取,然后写入各自的单独文件,例如线程1写入文件_1,线程2写入文件_2,等等 这适用于2/3个线程,但对于更多的线程,它似乎陷入了死锁,但我不确定问题的根源是什么 干杯!:) #包括“tape.h” #包括 #包括 #包括 #包括 #定义字节无符号字符 int present_file=0; pthread_t线程[100]; 整数偏移量[100]; 文件*文件; pthread\u mutex\u t read\u mutex=pth

我是C新手,有以下多线程场景,其中N个线程从单个二进制文件读取,然后写入各自的单独文件,例如线程1写入文件_1,线程2写入文件_2,等等

这适用于2/3个线程,但对于更多的线程,它似乎陷入了死锁,但我不确定问题的根源是什么

干杯!:)

#包括“tape.h”
#包括
#包括
#包括
#包括
#定义字节无符号字符
int present_file=0;
pthread_t线程[100];
整数偏移量[100];
文件*文件;
pthread\u mutex\u t read\u mutex=pthread\u mutex\u初始值设定项;
pthread\u mutex\u t finished\u read\u mutex=pthread\u mutex\u初始值设定项;
pthread\u mutex\u t file\u read=pthread\u mutex\u初始值设定项;
pthread_cond_t read_cond=pthread_cond_初始值设定项;
pthread_cond_t finished_read_cond=pthread_cond_初始值设定项;
int read=0;
int finished_reading=0;
int读取值;
大小文件长度;
int n_线程=0;
void*磁带读取器(void*args){
int offset=*((int*)参数);
文件*文件ptr;
如果(当前文件==1){
文件_ptr=fopen(“标题1”、“wb”);
}
else if(present_file==2){
文件_ptr=fopen(“标题2”、“wb”);
}
else if(present_file==3){
文件_ptr=fopen(“标题3”、“wb”);
}
else if(present_file==4){
文件_ptr=fopen(“标题4”、“wb”);
}
else if(present_file==5){
文件_ptr=fopen(“标题5”、“wb”);
}
else if(present_file==6){
文件_ptr=fopen(“标题6”、“wb”);
}
else if(present_file==7){
文件_ptr=fopen(“标题7”、“wb”);
}
else if(present_file==8){
文件_ptr=fopen(“标题8”、“wb”);
}
else if(present_file==9){
文件_ptr=fopen(“标题9”、“wb”);
}
else if(当前文件==10){
文件_ptr=fopen(“标题10”、“wb”);
}
否则{
文件_ptr=NULL;
}
while(read==0){
pthread_cond_wait(&read_cond,&read_mutex);
}
//线程开始读取
pthread_mutex_lock(&file_read);
字节缓冲区;
倒带(文件);
fseek(文件、偏移、搜索集);
对于(int i=0;i<读取值;i++){
if(i==文件长度){
i=0;
}
fread(&buffer,1,sizeof(buffer),file);
fwrite(&buffer,1,sizeof(buffer),file_ptr);
}
fclose(文件检索);
pthread_mutex_unlock(&file_read);
返回0;
}
int main(int argc,字符**argv){
如果(argc==1){
printf(“未插入磁带”);
返回1;
}
else if(argc==2){
file=fopen(argv[1],“rb”);
if(file==NULL){
printf(“无法读取磁带”);
返回1;
}
否则{
fseek(文件,0,SEEK_END);
文件长度=ftell(文件);
倒带(文件);
而(1){
字符用户输入[100];
整数偏移量;
scanf(“%s”,用户输入);
if(strcmp(用户输入,“退出”)==0){
返回0;
}
//printf(“%s\n”,用户输入);
if(strcmp(用户输入,“HEAD”)==0){
扫描频率(“%d”,偏移量(&F);
pthread_create(线程+当前文件、NULL、磁带读取器(void*)和偏移量);
n_线程++;
当前_文件++;
如果(偏移量>=0){
printf(“头%d位于+%d\n”,当前文件,偏移量);
printf(“\n”);
}
否则{
printf(“头%d位于%d\n”,当前文件,偏移量);
printf(“\n”);
}
}
if(strcmp(用户输入,“读取”)==0){
int read_用于;
scanf(“%d”,读取(&U));
read_value=读取的值;
read=1;
pthread_cond_信号(&read_cond);
//线程读取
printf(“已完成读取\n\n”);
对于(int i=0;i
我发现您代码的这一部分至少有两个错误:

while(read == 0){
   pthread_cond_wait(&read_cond, &read_mutex);
}
错误#1是在没有任何序列化的情况下读取
read
全局变量的值。由于
read
int
(而不是任何类型的
原子类型),因此这样做会调用未定义的行为(例如,线程A可能会更改
read
的值,而线程B可能永远不会“看到”更改)

错误#2是您正在调用
pthread\u cond\u wait()
,而
read\u mutex
尚未处于锁定状态。作为缔约国:

pthread_cond_wait()[函数为] 用于阻止条件变量。它们被互斥调用 将导致被调用线程锁定或未定义的行为


可能还有其他问题,但这正是我要解决的问题。

除了上述问题之外,还有另一个棘手的问题您不能保证线程中的
显示文件
与外部设置的值相同。
此代码:

      if(strcmp(userInput, "HEAD") == 0){

            scanf("%d", &offset);

            pthread_create(THREADS + present_file, NULL, tape_reader, (void *) &offset);

            n_threads++;

            present_file++;

            ...

        }
您不知道线程何时真正启动。因此,例如在第一次迭代中,它可能在
main
中增加
present\u file
后启动,而在第二次迭代中,它可能在增加
present\u file
前启动。然后,对于两个不同的线程,您将有类似的
显示\u文件
,从而可以访问同一文件

尽管这是一个非常棘手的问题,在正常情况下你可能看不到,但它也可能发生。因为你说你看到了更多线程的问题,我认为这将是你的问题的主要原因

您可以使用lock来访问其值以遇到问题。我个人更喜欢的另一种方法是使用分配的
struct
offset
present\u文件
传递给使用参数的线程

struct params
{
    int present_file;
    int offset;
};

...

      if(strcmp(userInput, "HEAD") == 0){

            scanf("%d", &offset);

            struct params *params = calloc(1, sizeof(*params));
            params->present_file = present_file;
            params->offset = offset;

            pthread_create(THREADS + present_file, NULL, tape_reader, (void *) params);

            n_threads++;

            present_file++;

            ...

        }

在阅读了线程中的值之后,请记住在线程中释放参数。

你对“C”是新手,但你已经跳入了“C”的最深处,决定做线程?已经做了2个月,并且每周都有一次在线讲座-我想这还是比较新的。@Hews,我想说是的
struct params
{
    int present_file;
    int offset;
};

...

      if(strcmp(userInput, "HEAD") == 0){

            scanf("%d", &offset);

            struct params *params = calloc(1, sizeof(*params));
            params->present_file = present_file;
            params->offset = offset;

            pthread_create(THREADS + present_file, NULL, tape_reader, (void *) params);

            n_threads++;

            present_file++;

            ...

        }