#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;
 }