使用 Mutex 和 Pthread 库的错误输出

Posted

技术标签:

【中文标题】使用 Mutex 和 Pthread 库的错误输出【英文标题】:Wrong Output using Mutex and Pthread Library 【发布时间】:2015-10-03 08:21:04 【问题描述】:

以下程序的目的是学习 Mutex 和 Pthread 库。 main() 创建三个线程。 (线程 1、2 和 3)。 每个线程一个接一个地顺序,每个文件(不同的文件)读取一个字符并存储到全局常量中。 示例线程 1 从 file1 读取字符 'a',然后等待线程 2 和 3 相同(即分别从 file2 和 file3 读取 'b' 和 'c')。 读取完成后,我们希望 main 将全局常量打印到 file.out

我尝试过相同的程序,但输出不正确。

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

char glob_var, strtemp[1024];
pthread_mutex_t lock;
int cnt = 0;
char inp[3][10] = "file-1.in", "file-2.in", "file-3.in";

void * thread_func(void * arg);

void * thread_func(void * arg)

    FILE *fp;
    char * argu = (char *)arg;
    fp = fopen(argu, "r");
    while (1) 
        pthread_mutex_lock(&lock);
        glob_var = fgetc(fp);
        if(feof(fp))
         
            pthread_mutex_unlock(&lock);
            break ;
        
        if (glob_var != '\n')
            strtemp[cnt++] = glob_var;
        pthread_mutex_unlock(&lock);
    
    fclose(fp);

    return (void *)0;


int main(void)

    FILE * fpout;
    pthread_t threads[3];
    int i = 0;

    fpout = fopen("file.out", "w");

    for (i = 0; i < 3; i++)
        pthread_create(&threads[i], NULL, thread_func, (void *)inp[i]);

    for (i = 0; i < 3; i++)
        pthread_join(threads[i], NULL);

    strtemp[cnt] = '\0';
    cnt = 0;

    while(1) 
        glob_var = strtemp[cnt++];
        fprintf(fpout, "%c\n", glob_var);
        if (strtemp[cnt] == '\0') 
            break;
        
    
    fclose(fpout);

    return 0;


Input File

File1 File2 File3
a     u     t
o     .     #
e     p     a
i     r     m
e     n     $

Output File

From Above Code         Desired Output
t                       a
#                       u
r                       t
a                       o
m                       .
!                       #
$                       e
s                       p
m                       a
u                       i
.                       r
p                       m
r                       e
n                       n

【问题讨论】:

您的互斥锁未正确初始化。 @EOF 虽然这是真的,但无论如何,互斥锁永远无法实现 OP 想要的...... 打开文件时,例如使用'fopen()',总是检查(!=NULL)返回值以确保操作成功 这一行:pthread_mutex_t lock; 应该是:pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 这一行:if(feof(fp)) 的问题是 feof() 直到尝试准备好输入文件的末尾之后才为真。那是一次迭代为时已晚。建议:将该行和前一行替换为:if(EOF == (glob_var = fgetc(fp))) 【参考方案1】:

您的mutex 仅确保不超过一个线程同时访问您的全局变量。它不能保证线程的调度顺序。对于您想要做的事情,mutex 是错误的同步原语,因为它正是为此而设计的:排除其他线程同时访问同一资源。

你想明确地允许一个特定的线程另一个线程之后。这可以使用semaphores 完成。每个线程需要一个。因此,在全局范围内声明第二个 sem_t 数组,其中包含 3 个条目,将第一个初始化为 1,其他初始化为 0。然后,将一个 线程号 (0 - 2) 传递给您的线程并执行一些操作喜欢:

int next = num + 1;
if (next > 2) next = 0;
sem_wait(sems[num]);
/* your code, accessing inp[num] */
sem_post(sems[next]);

【讨论】:

以上是关于使用 Mutex 和 Pthread 库的错误输出的主要内容,如果未能解决你的问题,请参考以下文章

pthread_mutex_lock和EAGAIN

pthread 的 Win32 替代方案

pthread_mutex_init返回值22代表啥含义

pthread_join 和 pthread_mutex_lock 有啥区别?

man pthread_mutex_init 或 man pthread_mutex_lock 没有结果的解决的方法

pthread_mutex_lock 和 pthread_mutex_lock 在另一个线程中