读者、写者问题优化
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_READERS 5
#define NUM_WRITERS 5
// 定义信号量和全局变量
sem_t sdata, srcount;
int readcount = 0;
// 建议在每个线程中使用局部随机数生成,不重复调用srand()(可在主线程调用一次)
void* reader(void* p) {
int id = *(int*)p + 1;
// 为每个线程设置一个线程局部种子,使用线程ID与时间混合生成
unsigned int seed = time(NULL) ^ id;
while (1) {
int sleepTime = rand_r(&seed) % 5 + 1; // 随机[1,5]秒
// 进入读者协议
sem_wait(&srcount);
readcount++;
if (readcount == 1) { // 第一个读者锁定共享资源
sem_wait(&sdata);
}
sem_post(&srcount);
// 模拟读操作
printf("读者 %d 开始读取...\n", id);
sleep(sleepTime);
printf("读者 %d 读取完成,耗时 %d 秒\n", id, sleepTime);
// 离开读者协议
sem_wait(&srcount);
readcount--;
if (readcount == 0) { // 最后一个读者释放共享资源
sem_post(&sdata);
}
sem_post(&srcount);
sleep(1); // 读者操作后稍作延时,再尝试下一次读取
}
return NULL;
}
void* writer(void* p) {
int id = *(int*)p + 1;
unsigned int seed = time(NULL) ^ id;
while (1) {
int sleepTime = rand_r(&seed) % 5 + 1; // 随机写入时间
// 写者请求进入共享资源
sem_wait(&sdata);
printf("写者 %d 开始写入...\n", id);
sleep(sleepTime);
printf("写者 %d 写入完成,耗时 %d 秒\n", id, sleepTime);
sem_post(&sdata);
sleep(1); // 写者操作后延时
}
return NULL;
}
int main(void) {
int i;
// 初始化信号量
sem_init(&sdata, 0, 1);
sem_init(&srcount, 0, 1);
pthread_t readers[NUM_READERS], writers[NUM_WRITERS];
int thread_ids[NUM_READERS > NUM_WRITERS ? NUM_READERS : NUM_WRITERS];
// 初始化随机种子只需一次(如果需要全局 seed 可在此设定)
srand(time(NULL));
// 创建读者线程
for (i = 0; i < NUM_READERS; i++) {
thread_ids[i] = i;
pthread_create(&readers[i], NULL, reader, &thread_ids[i]);
}
// 创建写者线程
for (i = 0; i < NUM_WRITERS; i++) {
thread_ids[i] = i;
pthread_create(&writers[i], NULL, writer, &thread_ids[i]);
}
// 等待所有线程结束(实际上本示例为无限循环,可使用其他退出条件)
for (i = 0; i < NUM_READERS; i++) {
pthread_join(readers[i], NULL);
}
for (i = 0; i < NUM_WRITERS; i++) {
pthread_join(writers[i], NULL);
}
sem_destroy(&sdata);
sem_destroy(&srcount);
return 0;
}