【问题标题】:Should we use mutex with semaphore to make a correct synchronization and to prevent a race condition?我们是否应该使用带信号量的互斥锁来进行正确的同步并防止竞争条件?
【发布时间】:2026-02-06 08:15:02
【问题描述】:

我试图看到竞争条件发生在消费者-生产者问题中, 所以我做了多个生产者和多个消费者。

据我所知,我需要为互斥量提供信号量: 竞争条件的互斥锁,因为多个生产者可以同时访问缓冲区。那么数据可能已损坏。

和信号量在生产者和消费者之间提供信号

这里的问题是当我不使用互斥锁时同步正确发生(我只使用信号量)。我的理解是正确的还是下面的代码有什么问题:

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

int buffer;
int loops = 0;

sem_t empty;
sem_t full;
sem_t mutex; //Adding MUTEX

void put(int value) {
    buffer = value;       
}

int get() {
    int b = buffer;      
    return b;
}



void *producer(void *arg) {
    int i;
    for (i = 0; i < loops; i++) {
        sem_wait(&empty);

        //sem_wait(&mutex);
        put(i);
        //printf("Data Set from %s, Data=%d\n", (char*) arg, i);
        //sem_post(&mutex);

        sem_post(&full);
    }
}

void *consumer(void *arg) {
    int i;
    for (i = 0; i < loops; i++) {
        sem_wait(&full);

        //sem_wait(&mutex);
        int b = get();
        //printf("Data recieved from %s, %d\n", (char*) arg, b);
        printf("%d\n", b);
        //sem_post(&mutex);

        sem_post(&empty);

    }
}

int main(int argc, char *argv[])
{
    if(argc < 2 ){
        printf("Needs 2nd arg for loop count variable.\n");
        return 1;
    }

    loops = atoi(argv[1]);

    sem_init(&empty, 0, 1); 
    sem_init(&full, 0, 0);    
    sem_init(&mutex, 0, 1);

    pthread_t pThreads[3];
    pthread_t cThreads[3];


    pthread_create(&cThreads[0], 0, consumer, (void*)"Consumer1");
    pthread_create(&cThreads[1], 0, consumer, (void*)"Consumer2");
    pthread_create(&cThreads[2], 0, consumer, (void*)"Consumer3");

    //Passing the name of the thread as paramter, Ignore attr
    pthread_create(&pThreads[0], 0, producer, (void*)"Producer1");
    pthread_create(&pThreads[1], 0, producer, (void*)"Producer2");
    pthread_create(&pThreads[2], 0, producer, (void*)"Producer3");


    pthread_join(pThreads[0], NULL);
    pthread_join(pThreads[1], NULL);
    pthread_join(pThreads[2], NULL);

    pthread_join(cThreads[0], NULL);
    pthread_join(cThreads[1], NULL);
    pthread_join(cThreads[2], NULL);

    return 0;
}

【问题讨论】:

  • 到底是什么问题? “同步”是什么意思?
  • 我的意思是;我预计生产者之间会在“缓冲区”上发生竞争条件,因为我没有提供互斥锁。我只使用信号量。但是上面的代码可以正常工作,没有问题(竞争条件)如果我放置多个生产者而不是只放置一个生产者,我想实际测试的是,竞争条件是否会发生(没有提供互斥锁,只有两个信号量)?

标签: pthreads mutex semaphore


【解决方案1】:

我相信我已经解决了问题。这是正在发生的事情

初始化信号量时,您将 empty 的线程数设置为 1,将 full 的线程数设置为 0

sem_init(&empty, 0, 1); 
sem_init(&full, 0, 0);    
sem_init(&mutex, 0, 1);

这意味着只有一个“空间”供线程进入临界区。换句话说,你的程序正在做的是

produce (empty is now 0, full has 1)
consume (full is now 0, empty has 0)
produce (empty is now 0, full has 1)
...

就好像你有一个令牌(或者,如果你喜欢,一个互斥体),你在消费者和生产者之间传递这个令牌。这实际上就是消费者-生产者问题的全部内容,只是在大多数情况下,我们担心有多个消费者和生产者同时工作(这意味着你有多个令牌)。在这里,因为你只有一个令牌,所以你基本上有一个互斥锁可以做的事情。

希望它有所帮助:)

【讨论】:

  • 正确——put()get() 函数在上述信号量初始化的情况下一次由单个线程访问。问题是,一旦你用更大的值初始化信号量,它就不会泛化。