sem_t
是 POSIX 线程库提供的一个信号量类型,用于同步多个线程对共享资源的访问。它可以用于线程之间的同步、进程之间的同步以及进程与线程之间的同步。
sem_t
类型的变量被称为信号量,它通常是一个非负整数,并且具有以下两个基本操作:
sem_wait()
:请求信号量,如果信号量的值大于 0,则将其减 1 并继续执行,否则当前线程将阻塞直到信号量的值变为大于 0。sem_post()
:释放信号量,将信号量的值加 1。
以下是一个使用 sem_t
实现生产者-消费者问题的示例代码:
#include <pthread.h>
#include <semaphore.h>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#define BUFFER_SIZE 10
#define MAX_ITEMS 10
#define NUM_PRODUCERS 2
#define NUM_CONSUMERS 2
sem_t mutex;
sem_t empty;
sem_t full;
int buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
void *producer(void *arg) {
int id = *(int*)arg;
for (int i = 0; i < MAX_ITEMS; i++) {
// wait for empty buffer slot
sem_wait(&empty);
// wait for exclusive access to the buffer
sem_wait(&mutex);
buffer[in] = i;
printf("Producer %d produced %d\n", id, i);
in = (in + 1) % BUFFER_SIZE;
// release exclusive access to the buffer
sem_post(&mutex);
// notify consumers that there is a new item in the buffer
sem_post(&full);
}
return NULL;
}
void *consumer(void *arg) {
int id = *(int*)arg;
int item;
for (int i = 0; i < MAX_ITEMS; i++) {
// wait for item in the buffer
sem_wait(&full);
// wait for exclusive access to the buffer
sem_wait(&mutex);
item = buffer[out];
printf("Consumer %d consumed %d\n", id, item);
out = (out + 1) % BUFFER_SIZE;
// release exclusive access to the buffer
sem_post(&mutex);
// notify producers that there is an empty slot in the buffer
sem_post(&empty);
}
return NULL;
}
int main() {
sem_init(&mutex, 0, 1);
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
int producer_ids[NUM_PRODUCERS];
int consumer_ids[NUM_CONSUMERS];
pthread_t producers[NUM_PRODUCERS];
pthread_t consumers[NUM_CONSUMERS];
for (int i = 0; i < NUM_PRODUCERS; i++) {
producer_ids[i] = i;
pthread_create(&producers[i], NULL, producer, &producer_ids[i]);
}
for (int i = 0; i < NUM_CONSUMERS; i++) {
consumer_ids[i] = i;
pthread_create(&consumers[i], NULL, consumer, &consumer_ids[i]);
}
for (int i = 0; i < NUM_PRODUCERS; i++) {
pthread_join(producers[i], NULL);
}
for (int i = 0; i < NUM_CONSUMERS; i++) {
pthread_join(consumers[i], NULL);
}
sem_destroy(&mutex);
sem_destroy(&empty);
sem_destroy(&full);
return 0;
}