种族问题,使用线程同步文本文件时

问题描述 投票:0回答:1

[嗯,我开始研究C语言中的POSIX线程,我试图使每个线程读取一行文件,直到并且很好,我设法通过条件变量进行同步来使其正常工作。 ,但是在读取文件的第一行时,两个线程可以同时读取,从而导致竞争条件问题,为什么会发生这种情况?我使用valgrind的helgrind工具对其进行了测试。

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


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

/*

  $cat file.txt
  test1
  test2
  test3
  test4
  test5
  test6
*/

FILE *fp;

void *func(void) {

      char c;

      fp = fopen("file.txt", "r");
      if(!fp) {
          perror("DEBUG: ");
          exit(EXIT_FAILURE);
      }

      pthread_mutex_lock(&mutex);
      while((c = fgetc(fp)) != EOF) {
         printf("TH = %zu CHARACTER = %c\n", pthread_self(), c);
         if(c == '\n') {
              pthread_cond_wait(&cond, &mutex);
            } else {
              pthread_cond_signal(&cond);
          }
      }
      pthread_mutex_unlock(&mutex);

      pthread_exit(NULL);
 }

 int main(void) {

    pthread_t thread1, thread2;

    pthread_create(&thread1, NULL, (void *)func, NULL);
    sleep(1);
    pthread_create(&thread2, NULL, (void *)func, NULL);

    pthread_join(thread2, NULL);

    fclose(fp);

    return 0;
}  
c multithreading synchronization pthreads posix
1个回答
0
投票

[当线程输入func时,它们都称为fp = fopen("file.txt", "r")。这意味着从理论上讲,当FILE*指向的fp从首先运行的线程下拔出时,您可以在任何步骤读取文件。

如果每个线程都需要读取整个文件,则应将FILE *fp声明拉到打开文件的位置,因此它是局部变量。如果采用这种方法,请确保同时关闭两个FILE*

如果他们应该共享当前设置的指针,那么您需要安全地打开文件。您可以根据需要通过两种方式完成此操作。

1)您应该更改声明,以将值也设置为NULL。然后在func内将pthread_mutex_lock(&mutex)移至通话上方fopen()。然后,仅在fopen()时调用fp == NULL

2)您也可以在启动pthread之前将对fopen()的调用移至main()。这样一来,只有一个线程不必担心要打开文件,并且它与您的fclose(fp)调用保持平衡,因此您知道fp的范围是有效的指针。

此外,通常最好将所有线程都加入。如果您使用的是Valgrind,它将因为线程1未连接而抱怨线程1泄漏。对于这样的简单情况以及线程的行为,在这种情况下无关紧要,但是如果您正在学习pthread,那么从一开始就拥有一个好习惯。


0
投票

两个线程都打开文件并从它们自己的FILE *中读取。

main函数中打开文件,并将FILE *作为参数传递给线程函数。

void *func(void *param) {

      char c;

      FILE *fp = param;
      pthread_mutex_lock(&mutex);
      while((c = fgetc(fp)) != EOF) {
         printf("TH = %zu CHARACTER = %c\n", pthread_self(), c);
         if(c == '\n') {
              pthread_cond_wait(&cond, &mutex);
            } else {
              pthread_cond_signal(&cond);
          }
      }
      pthread_mutex_unlock(&mutex);

      pthread_exit(NULL);
 }

 int main(void) {

    pthread_t thread1, thread2;

      FILE *fp = fopen("file.txt", "r");
      if(!fp) {
          perror("DEBUG: ");
          exit(EXIT_FAILURE);
      }

    pthread_create(&thread1, NULL, func, fp);
    sleep(1);
    pthread_create(&thread2, NULL, func, fp);

    pthread_join(thread2, NULL);

    fclose(fp);

    return 0;
}  
© www.soinside.com 2019 - 2024. All rights reserved.