簡體   English   中英

我如何從 C 線程開始讀取文件?

[英]How I do read a file from end to start with C threads?

我需要用 2 個線程讀取文件,其中一個將從頭到中讀取文件,另一個將從頭到中讀取文件。 我的文件中有 10 個浮點數。 前 5 個浮點數將由一個線程求和,最后 5 個浮點數將由另一個線程求和。 func1 沒問題,但我無法處理 func2 部分。

float sum=0,sum1=0,sum2=0,flo;  
int i=0;
FILE *fp;

 void *func1(void *param) {
      for(i=1;i<=5;i++) {
      fscanf(fp,"%f",&flo);
      sum1=flo+sum1;
}
      pthread_exit(0);
}
int main() {

   pthread_t tid;   
   pthread_attr_t attr;   
   pthread_attr_init(&attr);

   fp = fopen("input.txt","r");
   pthread_create(&tid, &attr, func1,fp);
   pthread_create(&tid, &attr, func2,fp);
   pthread_join(tid, NULL);
}

到目前為止,最簡單的技術是使用單個線程進行讀取。 但是,鑒於這是使用 POSIX 線程的練習,那么:

  • 您應該始終檢查fscanf()的返回值 - 線程或無線程。
  • 即使在非線程程序中,您也應該避免使用全局變量。
  • 線程和isum1flo都是全局的,你正在為可怕的競爭條件做准備。 您應該使用互斥鎖來防止對這些變量的並發訪問。 或者,更好的是,將它們全部設置為線程函數的本地。
  • 您還需要使函數返回適當的值。
  • 您應該使用傳遞給線程函數的參數。
  • 您應該將線程 ID 值保存在單獨的變量中,以便您可以等待兩個線程完成; 您的代碼只等待一個線程完成(第二個)。
  • 你應該打印結果。
  • 您不必擔心文件流上的同步 — POSIX 要求無論如何flockfile()發生這種情況(請參閱flockfile()及其近親都記錄在同一頁面上)。
  • 您應該同時提供func1()func2()來創建一個 MCVE(最小、完整、可驗證的示例。我假設兩個線程都可以使用相同的函數,這在上下文中並不是一個冒險的假設。

把它們放在一起導致:

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

struct tcb
{
    FILE *fp;
    double sum;
    int thread_num;
};

static void *func1(void *param)
{
    struct tcb *tcb = param;
    double sum1 = 0.0, flo;
    for (int i = 1; i <= 5; i++)
    {
        if (fscanf(tcb->fp, "%lf", &flo) != 1)
        {
            fprintf(stderr, "Thread %d failed to read value %d\n", tcb->thread_num, i);
            pthread_exit(0);
        }
        sum1 += flo;
    }
    tcb->sum = sum1;
    pthread_exit(0);
}

int main(void)
{
    FILE *fp;
    pthread_t tid1;
    pthread_t tid2;
    struct tcb tcb[2];
    pthread_attr_t attr;

    pthread_attr_init(&attr);
    const char *filename = "input.txt";

    if ((fp = fopen(filename, "r")) == NULL)
    {
        fprintf(stderr, "Failed to open file %s for reading\n", filename);
        exit(1);
    }
    tcb[0].fp = fp;
    tcb[0].thread_num = 0;
    tcb[0].sum = 0.0;
    tcb[1].fp = fp;
    tcb[1].thread_num = 1;
    tcb[1].sum = 0.0;
    pthread_create(&tid1, &attr, func1, &tcb[0]);
    pthread_create(&tid2, &attr, func1, &tcb[1]);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    printf("Total from thread 0 = %f\n", tcb[0].sum);
    printf("Total from thread 1 = %f\n", tcb[1].sum);
    printf("Grand total         = %f\n", tcb[0].sum + tcb[1].sum);
    return 0;
}

還有其他方法可以處理線程函數的輸入和輸出,但是創建一個簡單的結構似乎非常簡單和合適。

給定數據文件( input.txt ):

 23.192048
  4.128715
  3.465737
 74.307105
  4.329846
  6.098813
  9.497566
  6.988740
 11.530497
 53.262049
  9.469198
 41.305744

一次運行的輸出是:

Total from thread 0 = 87.377665
Total from thread 1 = 109.423451
Grand total         = 196.801116

其他運行給出了不同的值(另外一次運行反轉了兩個結果)。 這兩個總和對應於數據文件的第 6-10 行和第 1-5 行(有 12 行)。 這表明一個線程設法獲得調度並讀取其數據配額,然后讓另一個線程讀取下一個數據配額。 添加更多線程(使用循環和線程 ID 值數組)和更多數據可能會顯示 I/O 操作的不同交錯順序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM