允许多个线程同时获得信号量的使用场景通常是在资源共享的情况下。例如,假设有一个数据缓冲区,多个线程需要同时读写这个缓冲区,那么可以使用一个信号量来保证对缓冲区的互斥访问,同时设置信号量的计数器初始值为缓冲区的大小,这样就可以让多个线程同时访问缓冲区,只要缓冲区没有被占满或者没有被读空的情况下就可以继续访问。在这种情况下,每个线程在访问缓冲区之前需要获取信号量,如果信号量的计数器大于0,表示缓冲区中还有空闲位置,线程可以获取信号量并访问缓冲区,同时将信号量计数器减1,表示缓冲区的空闲位置减少了一个;如果信号量的计数器已经为0,表示缓冲区已经满了,线程需要等待其他线程释放信号量之后才能再次获取信号量并访问缓冲区。这样就可以实现多个线程同时访问缓冲区,同时保证对缓冲区的互斥访问。 给我一个上面这段话所描述的代码例程
时间: 2023-10-11 16:10:36 浏览: 77
下面是一个简单的使用信号量实现多线程访问共享缓冲区的例子:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
sem_t mutex, empty, full;
void *producer(void *arg);
void *consumer(void *arg);
int main(int argc, char *argv[]) {
pthread_t tid1, tid2;
sem_init(&mutex, 0, 1);
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
pthread_create(&tid1, NULL, producer, NULL);
pthread_create(&tid2, NULL, consumer, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
sem_destroy(&mutex);
sem_destroy(&empty);
sem_destroy(&full);
return 0;
}
void *producer(void *arg) {
int item;
while (1) {
item = rand() % 100;
sem_wait(&empty);
sem_wait(&mutex);
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
printf("Producer produced item %d\n", item);
sem_post(&mutex);
sem_post(&full);
usleep(100);
}
}
void *consumer(void *arg) {
int item;
while (1) {
sem_wait(&full);
sem_wait(&mutex);
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
printf("Consumer consumed item %d\n", item);
sem_post(&mutex);
sem_post(&empty);
usleep(1000);
}
}
```
在这个例子中,我们使用三个信号量来实现对共享缓冲区的互斥访问:
- `mutex`:保证对缓冲区的互斥访问,只有一个线程可以访问缓冲区。
- `empty`:表示缓冲区中还有多少个空闲位置,初始值为缓冲区的大小。
- `full`:表示缓冲区中已经有多少个数据项,初始值为0。
在生产者线程中,每次生产一个随机数,并将其放入缓冲区中。在访问缓冲区之前,需要先获取信号量`empty`和`mutex`,如果`empty`的计数器大于0,表示缓冲区还有空闲位置,线程可以获取`empty`和`mutex`,向缓冲区中添加数据,并将`in`指针向后移动一位。在访问缓冲区之后,需要释放`mutex`和`full`信号量,表示缓冲区中已经有了新的数据项。
在消费者线程中,每次从缓冲区中取出一个数据项并打印。在访问缓冲区之前,需要先获取信号量`full`和`mutex`,如果`full`的计数器大于0,表示缓冲区中已经有数据项,线程可以获取`full`和`mutex`,从缓冲区中取出数据项,并将`out`指针向后移动一位。在访问缓冲区之后,需要释放`mutex`和`empty`信号量,表示缓冲区中又有了空闲位置。
通过使用信号量来保证对共享缓冲区的互斥访问,我们可以实现多个生产者和消费者线程同时访问缓冲区,从而提高程序的并发度和效率。
阅读全文