C中的信号量和线程

时间:2013-11-27 04:10:38

标签: c multithreading semaphore

程序应该将3个文件名作为参数,创建2个线程,从第一个文件读取第一个线程,从第二个文件读取第二个线程,并且它们都写入第三个文件。最终,他们应该交替将他们正在阅读的文件中的每一行写入第三个文件。当我运行程序时,他们并不是真的交替;有时一个线程将其所有行写入文件,然后另一个线程将所有行写入文件。有时它们每个交替一行,然后是一对一个线程,然后一对另一个。有人能指出我在写方向上让每个线程交替写入文件吗?我发现当我更改sem_init函数的第3个参数时,它会影响线程交替的方式。

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


#define BADFILE  2
#define BADPARAM 3
#define DEBUG    1

sem_t mutex;

typedef struct {
    char *file;
    FILE *mf;
} read_args;

void error(char *msg, int code)
{
    fprintf(stderr, "Error: %s\nAborting.\n", msg);
    exit(code);
}

void *readFile1(void *p)
{

    read_args *param = (read_args *)p;
    FILE *f1;
    char *line;
    size_t len = 0;
    ssize_t read;
    int lineCount = 1;
    f1 = fopen(param->file, "r");
    if(f1 == NULL)
    {
        error("File not found.", BADFILE);
    }


    while((read = getline(&line, &len, f1)) != -1)
    {  
        sem_wait(&mutex);
        fprintf(param->mf,"%s: %d: %s", param->file, lineCount,line);

#if DEBUG        
        printf("%s: %d: %s", param->file, lineCount,line);
#endif 

        sem_post(&mutex);
        lineCount++;
    } 
    fclose(f1);
    pthread_exit(NULL);
}

void *readFile2(void *p)
{

    read_args *param = (read_args *)p;
    FILE *f1;
    char *line;
    size_t len = 0;
    ssize_t read;
    int lineCount = 1;
    f1 = fopen(param->file, "r");
    if(f1 == NULL)
    {
        error("File not found.", BADFILE);
    }
    //sem_wait(&mutex);
    while((read = getline(&line, &len, f1)) != -1)
    {  
        sem_wait(&mutex);
        fprintf(param->mf,"%s: %d: %s", param->file, lineCount,line);

#if DEBUG        
        printf("%s: %d: %s", param->file, lineCount,line);
#endif 

        sem_post(&mutex);
        lineCount++;
    }

    fclose(f1);
    pthread_exit(NULL);
}


int main(int argc, char **argv)
{
    FILE *f;
    char *mergedfile;
    pthread_t tid1, tid2;
    read_args *p1;
    read_args *p2;
    p1 = malloc(sizeof(read_args));
    p2 = malloc(sizeof(read_args));
    if(argc != 4)
    {
        error("Invalid parameters. Proper use: ./merge <file1> <file2>" 
            " <mergedfile>", BADPARAM);
    }

    p1->file = argv[1];
    p2->file = argv[2];

    mergedfile = argv[3];
    f = fopen(mergedfile, "w");
    if(f == NULL)
    {
        error("Can't open file.", BADFILE);
    }
    p1->mf = f;
    p2->mf = f;

    sem_init(&mutex, 0, 3);
    if(pthread_create(&tid1, NULL, readFile1, (void*)p1) < 0)
    {
        error("Can't create first thread", EXIT_FAILURE);
    }
    if(pthread_create(&tid2, NULL, readFile2, (void*)p2) < 0)
    {
        error("Can't create second thread", EXIT_FAILURE);
    }
    if(pthread_join(tid1, NULL) < 0)
    {
        error("Can't join first thread", EXIT_FAILURE);
    }
    if(pthread_join(tid2, NULL) < 0)
    {
        error("Can't join second thread", EXIT_FAILURE);
    }
    sem_destroy(&mutex);

    fclose(f);
    return(EXIT_SUCCESS);

}

1 个答案:

答案 0 :(得分:0)

您正在使用信号量作为互斥锁。这将保持一个线程写入而另一个被阻止,但不保证执行顺序。正如您所发现的,同一个线程可以连续多次获取信号量。每个线程都需要向另一个线程发出信号,表示轮到他们了。他们通过张贴来做到这一点。

如果使用第二个信号量,则可以强制线程交替。 Thread1需要在mutex1上等待并发布到mutex2。 Thread2等待mutex2并发布到mutex1。 Mutex1需要初始化为1,因此它可以先行; mutex2初始化为0所以它必须等到thread1先运行并发布才能执行任何操作。确保在pthread_exit之前发布到其他线程的互斥锁,否则另一个线程可能有更多内容要读,但它会死锁。

你也应该将lineCount的增量放在临界区内,因为它在线程之间共享。