выполнение выполнения попадает в бесконечный цикл - PullRequest
0 голосов
/ 06 февраля 2019

Я пытаюсь:

  • создал четыре потока (основной создает 3 потока, а поток 3 создает поток 4)
  • один объект общей памяти используется всеми потоками.
  • другой объект совместно используемой памяти распределяется между потоком два и потоком четыре.
  • Поток четыре ожидает сигнала из потока 2, пока не будет создан общий объект памяти.
  • все являются взаимоисключающими.

Но моя программа находится в бесконечном цикле.Нужна помощь для решения.

Ниже мой исходный код:

#include <assert.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>   /* for ftruncate */
#include <sys/mman.h> /* for shm_ and mmap */
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h>    /* For O_* constants */

pthread_t T1, T2, T3, T4;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_one;

int fd;
int *shared_heap;
int *shared_heap2;
int *shared_heap3;
int counter = 0;

//thread one creator func
// *argv is the shared mem obj which is passed while thread is created
void* task1(void *argv) {
    int *var = (int*) argv;
    pthread_mutex_lock(&mutex);
    *var += 1;
     pthread_mutex_unlock(&mutex);
    return NULL;
} 

//thread two creator func
// *argv is the shared mem obj which is passed while thread is created
void* task2(void *argv) {
    int *var = (int*) argv;
    pthread_mutex_lock(&mutex);
    *var += 1;

    pthread_mutex_unlock(&mutex);
    //another mutex to create another shared mem obj
    pthread_mutex_lock(&mutex2);
    shared_heap2 = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0);
    assert(shared_heap2);
    counter++;
    //signal 
    if (counter > 0) {
     pthread_cond_signal(&cond_one);
        printf("signal is sent \n");
   }
   pthread_mutex_unlock(&mutex2);

  return NULL;
  }

 //thread four creator func
 //created from thread three
 // *argv is the shared mem obj which is passed while thread is created
 void* task4(void *argv) {
    int *var = (int*) argv;
    pthread_mutex_lock(&mutex);
    *var += 1;
    pthread_mutex_unlock(&mutex);

    pthread_mutex_lock(&mutex2);

    //waiting for signal from thread two
    while (counter > 0) {
    pthread_cond_wait(&cond_one, &mutex2);
    printf("waiting for signal. \n");
 }

    *shared_heap2 = 9;
    pthread_mutex_unlock(&mutex2);


    return NULL;  
}

////thread three creator func
void* task3(void *argv) {
     int *var = (int*) argv;
     pthread_mutex_lock(&mutex);
     *var += 1;
    pthread_mutex_unlock(&mutex);

    //thread four is create from here
     assert(pthread_create(&T4, NULL, &task4, var) == 0);
    assert(pthread_join(T4, NULL) == 0);
     return NULL;
}

int main(void) {

    pthread_cond_init(&cond_one, NULL);
     fd = shm_open("test_shared_var_heap_local", O_CREAT | O_RDWR,S_IRUSR | S_IWUSR);
    assert(fd != -1);
    assert(ftruncate(fd, sizeof(int)) == 0);
    shared_heap = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0);

    assert(shared_heap);

    printf("main \n");
    //assert(shared_heap);

    assert(pthread_create(&T1, NULL, &task1, shared_heap) == 0);

    assert(pthread_create(&T2, NULL, &task2, shared_heap) == 0);

    assert(pthread_create(&T3, NULL, &task3, shared_heap) == 0);
    printf("three \n");

    assert(pthread_join(T1, NULL) == 0);
    assert(pthread_join(T3, NULL) == 0);
    assert(pthread_join(T2, NULL) == 0);

     return 0;
}

1 Ответ

0 голосов
/ 06 февраля 2019

Но моя программа попадает в бесконечный цикл.

вы делаете

while (counter > 0) {
  pthread_cond_wait(&cond_one, &mutex2);
  printf("waiting for signal. \n");
}

, но counter просто установлен на 1 один раз в task2 , нет причин выходить изthe while

В любом случае, это не единственная проблема, в task2 в mutext2 counter установлено в 1, и сигнал отправляется, поэтому

  • первая возможность задача 4 уже завершена до того, как было установлено значение 1, сигнал бесполезен

  • остальное Task2 быстрее запускается и получает mutex2 до task4 , поэтому, когда task4 получит mutex2 сигнал уже отправлен,но сигнал не буферизуется, поэтому он никогда не будет получен task4

Если вы хотите быть уверены, что код защищен mutex2 в task2 выполняется до того, как task4 завершает код, защищенный mutex2 :

  • counter все еще инициализируется в0: int counter = 0;
  • in task4 когда mutex2 просто установить counter в 1 и удалить бесполезный тест if (counter > 0) для отправки сигнала во всех случаях, прежде чем разблокировать mutext2
  • в task2 , когда mutext2 - получить, заменить while (counter > 0) { на if (counter == 0) {

на:

  • если task4 get mutex2 до task2 , поскольку counter по-прежнему 0 task4 ждетдля сигнала (который разблокирует mutext2 ) task2 может получить mutext2 , отправить сигнал и разблокировать mutext2 и завершить его, task4 получает сигнал (который блокирует mutext2 ), затем разблокирует mutext2 и завершает
  • , если task2 get mutext2 до task4 устанавливает counter на 1 и разблокирует mutext2 и завершает, task4 может получить mutext2 и выполняетне ждать сигнала, потому что колer равно 1, поэтому разблокируйте mutext2 и заканчивайте
...