Mutex тупик (pthread_mutex) - PullRequest
       69

Mutex тупик (pthread_mutex)

0 голосов
/ 23 июня 2019

Добрый вечер, ребята, я не могу понять, почему в этом коде я зашел в тупик. Я определил мьютексы, в частности:

  • mutex3: = 0 (заблокирован)
  • мьютекс2: = 1 (НЕ ЗАБЛОКИРОВАН)

У меня есть 2 процесса: отец и сын. У каждого есть N потоков, которые я передаю по аргументу. Потоки потомка конкурируют с потоками отца как «ресурс» (типичная проблема производителя / потребителя).

Заранее спасибо!

Полагаю, проблема здесь:

void * func_padre(void * n)
{
    while(1)
    {
        pthread_mutex_lock(&mutex2);
        printf("Scrivi messaggio: ");
        fflush(stdout);
        scanf("%[^\n]",(char *)addr_mem);
        getchar();
        pthread_mutex_unlock(&mutex3);

    }
}

void * func_figlio(void * n)
{
    while(1)
    {   
        pthread_mutex_lock(&mutex3);
        write(fd,addr_mem,4096);
        lseek(fd,0,SEEK_SET);
        memset(addr_mem,0,4096);
        pthread_mutex_unlock(&mutex2);
    }
}

КОД:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

void * addr_mem;
pthread_mutex_t mutex2,mutex3;
int fd;
void * func_padre(void * n)
{
    while(1)
    {
        pthread_mutex_lock(&mutex2);
        printf("Scrivi messaggio: ");
        fflush(stdout);
        scanf("%[^\n]",(char *)addr_mem);
        getchar();
        pthread_mutex_unlock(&mutex3);

    }
}

void * func_figlio(void * n)
{
    while(1)
    {   
        pthread_mutex_lock(&mutex3);
        write(fd,addr_mem,4096);
        lseek(fd,0,SEEK_SET);
        memset(addr_mem,0,4096);
        pthread_mutex_unlock(&mutex2);
    }
}

int main(int argc, char*argv[])
{
        if(argc<2)
        {
            printf("POCHI PARAMETRI\n");
            fflush(stdout);
            exit(-1);
        }

        int val=strtol(argv[2],0,10);

        fd = open(argv[1],O_CREAT|O_RDWR,0666);
        lseek(fd,0,SEEK_SET);//USELESS

        ///SHARED MEMORY
        int id_mem;


        id_mem = shmget(6543,4096,IPC_CREAT|0666);
        addr_mem = shmat(id_mem,NULL,0);
        /////////////////////

        /// MUTEX
        pthread_mutex_init(&mutex2,NULL);
        pthread_mutex_init(&mutex3,NULL);
        pthread_mutex_lock(&mutex3);
        /////////////////////
        pthread_t tid;
        int i=0;

        int pid;
        pid = fork();
        if(pid==0)
        {
            //CHILD
            for(i=0; i<val; i++)
                pthread_create(&tid,NULL,func_figlio,NULL);

            while(1)
            {   
                pthread_mutex_lock(&mutex3);
                write(fd,addr_mem,4096);
                memset(addr_mem,0,4096);
                pthread_mutex_unlock(&mutex2);
            }
        }
        else
        {
            //FATHER
            for(i=0; i<val; i++)
                pthread_create(&tid,NULL,func_padre,NULL);

                while(1)
                {
                    pthread_mutex_lock(&mutex2);
                    printf("Scrivi messaggio: ");
                    fflush(stdout);
                    scanf("%[^\n]",(char *)addr_mem);
                    getchar();
                    pthread_mutex_unlock(&mutex3);

                }
        }
}

Ответы [ 2 ]

1 голос
/ 24 июня 2019

Ваша проблема не в тупике, это просто глючный код.Поток не может разблокировать мьютекс, который он не заблокировал.Ваши while зацикливают все мьютексы разблокировки, которые они не держат, и никогда не разблокируют мьютексы, которые они делают удерживают.

0 голосов
/ 25 июня 2019

предложить:

имеют глобальную переменную, которая циклически перебирает ограниченный набор значений, скажем: 0, 1, 0 ...

Используйте мьютекс, чтобы остановить развитие других потоков, т.е.

When a call (in thread) returns from locking the mutex, 
then check 
    if the value in the global variable is for 'this' thread.
    then  
        process the thread activities,  
        increment the global variable,
    endif 
endif
unlock the mutex
call nanosleep() to delay for a while to allow other threads to run
...