我正在研究互斥体,我被困在练习中。对于给定目录中的每个文件,我必须创建一个线程来读取它并显示其内容(如果顺序不正确则没问题)。
到目前为止,线程正在运行此函数:
void * reader_thread (void * arg)
{
char * file_path = (char*)arg;
FILE * f;
char temp[20];
int value;
f=fopen(file_path, "r");
printf("Opened %s.\n",file_path);
while (fscanf(f, "%s",temp)!=EOF)
if (!get_number (temp, &value)) /*Gets int value from given string (if numeric)*/
printf("Thread %lu -> %s: %d\n", pthread_self(), file_path, value );
fclose(f);
pthread_exit(NULL);
}
由接收DIR
指针的函数调用,该指针先前由opendir()
创建。
(我在这里省略了一些错误检查以使其更清晰,但我完全没有错误。)
int readfiles (DIR * dir, char * path)
{
struct dirent * temp = NULL;
char * file_path;
pthread_t thList [MAX_THREADS];
int nThreads=0, i;
memset(thList, 0, sizeof(pthread_t)*MAX_THREADS);
file_path=malloc((257+strlen(path))*sizeof(char));
while((temp = readdir (dir))!=NULL && nThreads<MAX_THREADS) /*Reads files from dir*/
{
if (temp->d_name[0] != '.') /*Ignores the ones beggining with '.'*/
{
get_file_path(path, temp->d_name, file_path); /*Computes rute (overwritten every iteration)*/
printf("Got %s.\n", file_path);
pthread_create(&thList[nThreads], NULL, reader_thread, (void * )file_path)
nThreads++;
}
}
printf("readdir: %s\n", strerror (errno )); /*Just in case*/
for (i=0; i<nThreads ; i++)
pthread_join(thList[i], NULL)
if (file_path)
free(file_path);
return 0;
}
我的问题是,尽管路径计算得很好,但线程似乎没有收到正确的参数。他们都读了同一个文件。这是我得到的输出:
Got test/testB.
Got test/testA.
readdir: Success
Opened test/testA.
Thread 139976911939328 -> test/testA: 3536
Thread 139976911939328 -> test/testA: 37
Thread 139976911939328 -> test/testA: -38
Thread 139976911939328 -> test/testA: -985
Opened test/testA.
Thread 139976903546624 -> test/testA: 3536
Thread 139976903546624 -> test/testA: 37
Thread 139976903546624 -> test/testA: -38
Thread 139976903546624 -> test/testA: -985
如果我在下一个开始之前加入线程,它就可以了。所以我假设某个地方有一个关键部分,但我真的不知道如何找到它。我试过静音整个线程函数:
void * reader_thread (void * arg)
{
pthread_mutex_lock(&mutex_file);
/*...*/
pthread_mutex_unlock(&mutex_file);
}
并且,在第二个函数中静音while循环。即便是在同一时间。但它不会以任何方式起作用。顺便说一下,mutex_file是一个全局变量,由pthread_mutex_init()
中的main()
初始化。
我真的很感激这方面的建议,因为我真的不知道我做错了什么。我也很欣赏一些好的参考书或书,因为互斥体和System V信号量对我来说感觉有点困难。
非常感谢。
答案 0 :(得分:3)
好吧,您将与文件路径完全相同的指针传递给两个线程。结果,他们从同一个字符串中读取文件名,最后读取同一个文件。实际上,你在这里有点幸运,因为实际上你有一个竞争条件 - 你通过file_path
更新字符串指针的内容,同时启动从该指针读取的线程,所以你可能最终得到一个线程在更改内存时读取内存。你要做的是分别为每个线程分配一个参数(即在malloc
循环中调用while
和相关逻辑),然后在退出线程后释放这些参数。
答案 1 :(得分:3)
看起来你正在为所有线程使用相同的file_path缓冲区,只是使用下一个名称反复加载它。您需要为每个线程分配一个新字符串,并让每个线程在使用后删除该字符串。
修改的
由于你已经有了一个线程数组,你可以创建一个char []的并行数组,每个数组都包含相应线程的文件名。这样可以避免malloc / free。