gpt4 book ai didi

c - 为什么我的多线程程序有时会阻塞?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:47:56 25 4
gpt4 key购买 nike

我们必须编写一个程序,它有 2 个线程。其中之一逐个读取内容 token 并将它们存储到一个数组中。另一个从数组中读取标记并将其写入文件。这是代码:

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

#define MAX 10


int buffer[MAX];
int buf_pos; // the actual position of the buffer

void copy();

int flag; // if flag is 0, the whole content of the file was read
FILE *source;
FILE *dest;

// read the content of a file token by token and stores it into a buffer
void *read_from_file();

// write the content of a buffer token by token into a file
void *write_to_file();

pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex;

int main( int argc, char *argv[] )
{
flag = 1;
pthread_t writer;
pthread_t reader;
pthread_mutex_init( &mutex, NULL );

if( argc != 3 )
{
printf( "Error\n" );
exit( EXIT_FAILURE );
}

source = fopen( argv[1], "r" );
dest = fopen( argv[2], "w" );
if( source == NULL || dest == NULL )
{
printf( "Error\n" );
exit( EXIT_FAILURE );
}

pthread_create( &reader, NULL, read_from_file, NULL );
pthread_create( &writer, NULL, write_to_file, NULL );

pthread_join( reader, NULL );
pthread_join( writer, NULL );

}

void *read_from_file()
{
int c;
while( ( c = getc( source ) ) != EOF )
{
if( buf_pos < MAX - 1 ) // the buffer is not full
{
pthread_mutex_lock( &mutex );
buffer[buf_pos++] = c;
pthread_mutex_unlock( &mutex );
pthread_cond_signal( &condition );
}
else
{
buffer[buf_pos++] = c; // store the last token
pthread_mutex_lock( &mutex );
pthread_cond_wait( &condition, &mutex ); // wait until the other thread sends a signal
pthread_mutex_unlock( &mutex );
}
}
flag = 0; // EOF
return NULL;
}


void *write_to_file()
{
int c;
while( flag || buf_pos > 0 )
{
if( buf_pos > 0 ) // The buffer is not empty
{
fputc( buffer[0], dest ); // write the first token into file
pthread_mutex_lock( &mutex );
copy();
--buf_pos;
pthread_mutex_unlock( &mutex );
pthread_cond_signal( &condition );
}
else
{
pthread_mutex_lock( &mutex );
pthread_cond_wait( &condition, &mutex );
pthread_mutex_unlock( &mutex );
}
}
return NULL;
}

void copy()
{
int i = 0;
for( ; i < buf_pos - 1; ++i )
buffer[i] = buffer[i + 1];
}

如果我想运行这个程序,它有时会阻塞,但我不知道为什么。但如果程序终止,输出文件与输入文件相同。有人可以向我解释一下,为什么会发生这种情况吗?

最佳答案

代码有很多问题,但您锁定的原因很可能是您在没有锁定互斥锁的情况下发送信号,并且没有在锁定互斥锁的情况下检查您的条件。两者都是必要的,以确保您最终不会丢失信号。

正如 Useless 所指出的,确保您知道您的共享变量是什么,并且在必要时它们是互斥保护的。例如,您的 buf_pos 在您的阅读器线程中被修改而没有保护,并且在两个线程中用作没有互斥保护的等待条件。

此外,在执行 pthread_cond_wait 时,您通常需要一个保护表达式来确保您不会对所谓的虚假唤醒使用react(查看 http://linux.die.net/man/3/pthread_cond_wait 处的“条件等待语义”部分) ,并确保您正在等待的条件在测试它和开始等待之间实际上没有发生。

例如,在您的作者线程中,您可以:

pthread_mutex_lock(&mutex);
while(buf_pos == 0) pthread_cond_wait(&condition, &mutex);
pthread_mutex_unlock(&mutex);

但是,还是要彻底检查您的程序,确定您的共享变量,并确保它们在必要时受互斥保护。此外,您只需要对共享数据进行写访问互斥保护是不正确的。在某些情况下,您可以在读取共享变量时移除互斥锁保护,但您必须分析代码以确保确实如此。

关于c - 为什么我的多线程程序有时会阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23767585/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com