Почему семафор не блокирует второй поток? (С) - PullRequest
1 голос
/ 04 ноября 2019

Я хочу написать простую программу на C, чтобы лучше понимать семафоры. Есть два потока, и они оба вызывают одну и ту же функцию. Первый увеличивает глобальную переменную, а второй поток уменьшает глобальную переменную.

Я пытаюсь заблокировать использование функции вторым потоком до того, как первый поток завершит свою работу. Но я все еще получаю неправильный ответ: -2000. Похоже, что оба потока имеют смещение -1. Как я могу это исправить, чтобы вывод всегда был 0? Я думал, что sem_wait внутри функции должен блокировать второй поток, пока не закончится первый. Следовательно, смещение должно было остаться 1.

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

#define NUM_LOOPS 1000
long long counter = 0;
sem_t sem;
sem_t sem1;
void* counting_thread(void* arg) {
    sem_wait(&sem);
    int offset = *(int*) arg;
    int i;
    for(i = 0; i < NUM_LOOPS; i++){
        //sem_wait(&sem);
        counter += offset;
        printf("offset = %d\n", offset1);


        //sem_post(&sem);
    }
    sem_post(&sem);

    pthread_exit(NULL);
}

int main() {
    sem_init(&sem, 0, 1);

    pthread_t th1;
    int offset = 1;
    pthread_create(&th1, NULL, &counting_thread, &offset);
    //sem_post(&sem1);

    pthread_t th2;
    offset = -1;
    pthread_create(&th2, NULL, &counting_thread, &offset);

    pthread_join(th1, NULL);
    pthread_join(th2, NULL);

    printf("Finnal counter value: %lld\n", counter);
    sem_destroy(&sem);
    return 0;
}

1 Ответ

2 голосов
/ 04 ноября 2019

Согласно справочной странице pthread_create

Примечания См. Pthread_self (3) для получения дополнительной информации об идентификаторе потока, возвращенном в * thread потоком pthread_create (). Если не используются политики планирования в реальном времени, после вызова pthread_create (), не определяет, какой поток - вызывающая сторона или новый поток - будет выполняться следующим образом.

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


Вы можете использовать условную переменнуюдля синхронизации.

Например:

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

#define NUM_LOOPS 1000
long long counter = 0;
sem_t sem;
sem_t sem1;
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER; 
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 


void* counting_thread(void* arg) {
    sem_wait(&sem);
    int offset = *(int*) arg;
    pthread_cond_signal(&cond1); 

    int i;
    for(i = 0; i < NUM_LOOPS; i++){
      counter += offset;
        printf("offset = %d\n", offset);

  }
    sem_post(&sem);

    pthread_exit(NULL);
}

int main() {
    sem_init(&sem, 0, 1); 

    int offset = 1;
    pthread_t th1;
    pthread_create(&th1, NULL, &counting_thread, &offset);


    pthread_cond_wait(&cond1, &lock);
    pthread_t th2;
    offset = -1;
    pthread_create(&th2, NULL, &counting_thread, &offset);

    pthread_join(th1, NULL);
    pthread_join(th2, NULL);

    printf("Finnal counter value: %lld\n", counter);
    sem_destroy(&sem);
    return 0;
}
...