📜  二进制信号量和互斥量的区别(1)

📅  最后修改于: 2023-12-03 15:21:40.634000             🧑  作者: Mango

二进制信号量和互斥量的区别

1. 二进制信号量

二进制信号量是一种利用二进制值来控制多个进程协同工作的机制。它只有两个取值:1和0,分别表示资源可用和资源不可用。当一个进程需要访问某个共享资源时,它首先需要检查信号量的值是否为1。如果是,表示资源空闲,进程可以获取该资源并将信号量的值设为0;否则表示资源已被其他进程占用,该进程只能等待。当其他进程释放资源后,它们会唤醒等待的进程,使其重新检查信号量的值并争夺资源。

二进制信号量主要用于进程间同步和互斥,特别是在生产者-消费者模型中经常使用。它的优点是实现简单,只需要一次赋值操作即可控制多个进程;缺点是不支持多个进程同时访问资源,因此在某些场景下可能会出现饥饿或死锁现象。

2. 互斥量

互斥量是一种用于保护共享资源不会被多个线程同时访问的机制。它可以被看作是一种计数信号量,只有两种值:0和1。当一个线程要访问某个共享资源时,它需要先尝试获取互斥量。如果互斥量的值为0,表示该资源已被其他线程占用,该线程则会进入阻塞状态直至互斥量的值变为1;否则表示该资源空闲,该线程可以获取该资源并将互斥量的值设为0。当线程使用完共享资源后,它必须释放互斥量,使其值变为1,以便其他线程可以继续访问该资源。

互斥量可以保证共享资源在任意时刻只能被一个线程访问,从而避免了竞态条件和数据不一致的问题。它的优点是支持多个线程同时访问资源,且可以避免饥饿和死锁现象;缺点是实现相对复杂,需要注意加锁和解锁的时机,否则可能会导致线程无法释放资源或者导致资源竞争。

3. 二进制信号量和互斥量的适用场景

二进制信号量适用于以下场景:

  • 进程间同步和互斥;
  • 生产者-消费者模型。

互斥量适用于以下场景:

  • 线程间同步和互斥;
  • 多个线程访问共享资源时,需要保证数据一致性和避免竞态条件。
4. 示例代码
4.1 二进制信号量
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>

#define MAX_COUNT 10

sem_t bin_sem;

void *producer(void *arg)
{
    int i;
    for (i = 0; i < MAX_COUNT; i++) {
        sem_wait(&bin_sem);
        printf("Producer: produce item %d\n", i);
        sem_post(&bin_sem);
    }
    pthread_exit(NULL);
}

void *consumer(void *arg)
{
    int i;
    for (i = 0; i < MAX_COUNT; i++) {
        sem_wait(&bin_sem);
        printf("Consumer: consume item %d\n", i);
        sem_post(&bin_sem);
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_t tid_producer, tid_consumer;

    sem_init(&bin_sem, 0, 1);

    pthread_create(&tid_producer, NULL, producer, NULL);
    pthread_create(&tid_consumer, NULL, consumer, NULL);

    pthread_join(tid_producer, NULL);
    pthread_join(tid_consumer, NULL);

    sem_destroy(&bin_sem);

    return 0;
}
4.2 互斥量
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define MAX_COUNT 10

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *worker(void *arg)
{
    int i;
    for (i = 0; i < MAX_COUNT; i++) {
        pthread_mutex_lock(&mutex);
        printf("Worker: process item %d\n", i);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_t tid_worker1, tid_worker2;

    pthread_create(&tid_worker1, NULL, worker, NULL);
    pthread_create(&tid_worker2, NULL, worker, NULL);

    pthread_join(tid_worker1, NULL);
    pthread_join(tid_worker2, NULL);

    pthread_mutex_destroy(&mutex);

    return 0;
}

以上示例代码可以在Linux平台上编译运行,需要链接pthread库和rt库(只有使用semaphore.h头文件时需要)。