sem_init и pthread_mutex_init - PullRequest
       64

sem_init и pthread_mutex_init

0 голосов
/ 05 марта 2020

Я писал 2 одинаковых кода для печати нечетных и четных чисел из заданного числа, используя блокировку мьютекса и семафор. Оба кода работают нормально.

Но, при использовании блокировки мьютекса, даже если я не объявляю функцию pthread_mutex_init, программа все равно выполняется без проблем. Но это не относится к семафору. Для этого случая я должен объявить sem_init в main (), иначе выполнение программы застрянет в sem_wait() (найден после отладки).

Итак, как в случае блокировки мьютекса, даже без объявления init (), программа выполняется?

Для справки, я прилагаю код семафора.

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

sem_t mutex;
pthread_t tid[2];
unsigned int shared_data[] = {23,45,67,44,56,78,91,102};
unsigned int rc;
int len=(sizeof(shared_data)/sizeof(shared_data[0]));
int i=0;

void *even(void *arg) {
    rc = sem_wait(&mutex);
    int temp = rc;
    if(rc)
        printf("Semaphore failed\n");

    do{
        if(shared_data[i] %2 == 0) {
            printf("Even: %d\n",shared_data[i]);
            i++;
        }
        else
            rc = sem_post(&mutex);
    }while(i<len);
}

void *odd(void *arg) {
    rc = sem_wait(&mutex);
    if(rc)
        printf("Semaphore failed\n");

    do {
        if(shared_data[i] %2 != 0) {
            printf("Odd: %d\n",shared_data[i]);
            i++;
        }
        else
            rc = sem_post(&mutex);
    }while(i<len);
}

int main() {
    sem_init(&mutex, 0,1);
    pthread_create(&tid[0], 0, &even, 0);
    pthread_create(&tid[1], 0, &odd, 0);

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);

    sem_destroy(&mutex);

    return 0;
}

РЕДАКТИРОВАТЬ: также присоединение кода блокировки мьютекса.

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

pthread_t tid[2];
unsigned int shared_data []= {23,45,67,44,56,78,91,102};
pthread_mutex_t mutex;
unsigned int rc;
int len=(sizeof(shared_data)/sizeof(shared_data[0]));
int i=0;

void* PrintEvenNos(void *ptr)
{
    rc = pthread_mutex_lock(&mutex);
    if(rc)
        printf("Mutex lock has failed\n");
    do
    {
       if(shared_data[i]%2 == 0)
       {
         printf("Even:%d\n",shared_data[i]);
         i++;
       } else {
          rc=pthread_mutex_unlock(&mutex);
       }
    } while(i<len);
}

void* PrintOddNos(void* ptr1)
{
    rc = pthread_mutex_lock(&mutex);
    if(rc)
        printf("Mutex lock has failed\n");
    do
    {
       if(shared_data[i]%2 != 0)
       {
         printf("Odd:%d\n",shared_data[i]);
         i++;
       } else {
          rc=pthread_mutex_unlock(&mutex);
       }
    } while(i<len);
}

void main(void)
{   
    pthread_create(&tid[0],0,PrintEvenNos,0);
    pthread_create(&tid[1],0,PrintOddNos,0);

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);
}

Ответы [ 3 ]

2 голосов
/ 05 марта 2020

Итак, как в случае блокировки мьютекса, даже без объявления init (), программа выполняется?

Это неопределенное поведение , поэтому есть нет правильного результата. По POSIX pthread_mutex_lock():

Если mutex не относится к инициализированному объекту мьютекса, поведение pthread_mutex_lock(), pthread_mutex_trylock() и pthread_mutex_unlock() undefined.

«Похоже, что работает» является одним из возможных результатов неопределенного поведения.

0 голосов
/ 05 марта 2020

Оба кода работают нормально.

Нет, они не работают; но сначала:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

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

Один из ваших потоков (четный, нечетный) получает блокировку. В случае четного, когда i равно 0,1,2,5 или 6; Вы разблокируете его, что позволит odd () продолжить. В случае нечетного, когда я 3,4,5 или 7, вы разблокируете его, что позволит даже () продолжить. Так что в вашей логике c блокировка вообще ничего не делает.

Кроме того, семафоры являются счетчиками; поэтому, когда вы отпускаете его 5 раз, вы разрешаете продолжить следующие 5 sem_waits. Простые мьютексы - это ворота, так что только первая разблокировка имеет какой-либо эффект, последующие 4 - ошибки. Вы не проверяете статус ошибки разблокировки, которая обычно выявляет ошибки logi c.

fwiw, на macos обе функции pthread_mutex_lock () сообщают об ошибке.

0 голосов
/ 05 марта 2020

У вас есть sem_init вызов для sem_t mutex;.

Но pthread_mutex_init вызов отсутствует для pthread_mutex_t mutex;.

...