проблема синхронизации в нескольких потоках нескольких процессов - PullRequest
0 голосов
/ 29 сентября 2018

У меня есть код.Есть 2 процесса.Родитель является автором файла a.txt.Child - читатель на a.txt.Parent имеет 2 темы, а child - 2 темы.Родительский 1-й поток открывает файл parent1.txt.читает 128 символов.пишет во 2-й поток .txt. Родитель открывает файл parent2.txt.reads 128 символов.пишет в .txt.1-ый поток ребенка читает 128 символов из a.txt и записывает в child1.txt.2-ой поток ребенка читает 128 символов из a.txt и child2.txt.Любой родительский поток после записи должен генерировать событие и вызывать дочерние потоки читателя. Я реализовал решение, используя мьютекс и переменную условия. Потоки автора родительского потока генерируют pthread_cond_signal после записи в a.txt.1> Но после этого потоки читателя не запускаются.оба родительских потока выполняются в цикле.2> Родительский читает frm parent1.txt.Хлеб успешен.Но когда он пишет в .txt, это не удачно.Файл .txt всегда пуст. Я думаю, что мьютекс нельзя использовать между несколькими процессами.Это может быть 1 проблема

My code is as follows


  #include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;

FILE*fd,*fdRead1,*fdRead2,*fdWrite1,*fdWrite2;

pthread_mutex_t *mut1;
pthread_mutexattr_t attrmutex;

pthread_cond_t  *cond_var;
pthread_condattr_t attrcond;

#define OKTOWRITE "/condwrite"
#define MESSAGE "/msg"
#define MUTEX "/mutex_lock"

void* R1(void *)
{
    char buf[128];
    int size;
    fdWrite1 = fopen("child1.txt","w+");
    cout<<"R1Thread"<<endl; 
    for(int i=0;i<10;i++)
    {
    cout<<"R1Thread-1"<<endl; 
        pthread_mutex_lock(mut1);
        pthread_cond_wait(cond_var,mut1);
    cout<<"R1Thread-2"<<endl; 
        size = fread(buf,128,1,fd);
        fwrite(buf,size,1,fdWrite1);
        pthread_mutex_unlock(mut1);
    }
    fclose(fdWrite1);
}

void* R2(void *)
{
    char buf[128];
    int size;
    fdWrite2 = fopen("child2.txt","w+");
    cout<<"R2Thread"<<endl; 
    for(int i=0;i<10;i++)
    {
    cout<<"R2Thread-1"<<endl; 
        pthread_mutex_lock(mut1);
        pthread_cond_wait(cond_var,mut1);
    cout<<"R2Thread-2"<<endl; 
        size = fread(buf,128,1,fd);
        fwrite(buf,size,1,fdWrite2);
        pthread_mutex_unlock(mut1);

    }
    fclose(fdWrite2);

}


void* W1(void *)
{
    char buf[128];
    int size;
    fdRead1 = fopen("parent1.txt","r");
    for(int i=0;i<10;i++)
    {
        pthread_mutex_lock(mut1);
        size = fread(buf,128,1,fdRead1);
        fwrite(buf,size,1,fd);
        pthread_cond_signal(cond_var);
    cout<<"W2Thread-1"<<endl; 
        pthread_mutex_unlock(mut1);
        sleep(10);
    }
    fclose(fdRead1);

}

void* W2(void *)
{
    char buf[128];
    int size;
    fdRead2 = fopen("parent2.txt","r");
    for(int i=0;i<10;i++)
    {
        pthread_mutex_lock(mut1);
        size = fread(buf,128,1,fdRead2);
        fwrite(buf,size,1,fd);
        pthread_cond_signal(cond_var);
    cout<<"W2Thread-1"<<endl; 
        pthread_mutex_unlock(mut1);
        sleep(1000);

    }
    fclose(fdRead2);

}


int main()
{
int des_cond, des_msg, des_mutex;
int mode = S_IRWXU | S_IRWXG;

des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR | O_TRUNC, mode);

if (des_mutex < 0) {
    perror("failure on shm_open on des_mutex");
    exit(1);
}

if (ftruncate(des_mutex, sizeof(pthread_mutex_t)) == -1) {
    perror("Error on ftruncate to sizeof pthread_cond_t\n");
    exit(-1);
}

mut1 = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t),
        PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0);

if (mut1 == MAP_FAILED ) {
    perror("Error on mmap on mutex\n");
    exit(1);
}

des_cond = shm_open(OKTOWRITE, O_CREAT | O_RDWR | O_TRUNC, mode);

if (des_cond < 0) {
    perror("failure on shm_open on des_cond");
    exit(1);
}

if (ftruncate(des_cond, sizeof(pthread_cond_t)) == -1) {
    perror("Error on ftruncate to sizeof pthread_cond_t\n");
    exit(-1);
}

cond_var = (pthread_cond_t*) mmap(NULL, sizeof(pthread_cond_t),
        PROT_READ | PROT_WRITE, MAP_SHARED, des_cond, 0);

if (cond_var == MAP_FAILED ) {
    perror("Error on mmap on condition\n");
    exit(1);
}

/* Initialise attribute to mutex. */
pthread_mutexattr_init(&attrmutex);
pthread_mutexattr_setpshared(&attrmutex, PTHREAD_PROCESS_SHARED);

/* Allocate memory to pmutex here. */

/* Initialise mutex. */
pthread_mutex_init(mut1, &attrmutex);
/* Initialise attribute to condition. */
pthread_condattr_init(&attrcond);
pthread_condattr_setpshared(&attrcond, PTHREAD_PROCESS_SHARED);

/* Allocate memory to pcond here. */

/* Initialise condition. */
pthread_cond_init(cond_var, &attrcond);



    pthread_t thR1,thR2,thW1,thW2;
    fd = fopen("a.txt","w+");
    int res = fork();
    if(res<0) perror("error forking\n");
    if(res==0)//child
    {
        cout<<"child created"<<endl;
        pthread_create(&thR1,0,R1,0);
        //pthread_create(&thR2,0,R2,0);
        pthread_join(thR1,0);
        //pthread_join(thR2,0);
        fclose(fd);
    }
    else//parent
    {
        //fdRead = fopen("parent.txt","r");
        pthread_create(&thW1,0,W1,0);
        //pthread_create(&thW2,0,W2,0);
        pthread_join(thW1,0);
        //pthread_join(thW2,0);
        fclose(fd);
        wait(0);
    } 
}

Вывод выглядит следующим образом:

child created
W2Thread-1
R1Thread
R1Thread-1
W2Thread-1
W2Thread-1
W2Thread-1
W2Thread-1
W2Thread-1
W2Thread-1
W2Thread-1
W2Thread-1

Условное ожидание в child никогда не выходит.

1 Ответ

0 голосов
/ 29 сентября 2018

Существуют потенциальные проблемы с использованием нескольких процессов, каждый с несколькими потоками, но они в основном вращаются вокруг состояния программы во время разветвления.Поскольку ваша программа разветвляется до того, как она создаст какие-либо дополнительные потоки, вы можете быть уверены в ее состоянии в это время, и, в частности, вы можете быть уверены, что ее один поток в это время не выполняется в критической секции.Это нормально.

Однако вам не хватает двух ключевых деталей:

  1. Несмотря на то, что вы устанавливаете мьютекс как общий для процесса, версия кода, которую вы изначально представилине удалось сделать то же самое для условной переменной.

  2. Установка pthread_* объектов синхронизации для совместного использования в процессе необходима, но не достаточна для межпроцессного использования.Для этого вам нужно, чтобы объекты синхронизации находились в общей памяти, доступ к которой имеют все участвующие процессы.Только так все процессы могут обращаться к одним и тем же объектам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...