读者-写者问题

这是这学期操作系统课的第一次实验:分别实现读者优先和写者优先的读者写者问题。
这次的实验都基于Ubuntu系统通过C语言实现。本实验参考了这篇文章

读者优先和写者优先的唯一区别是:
其他读者正在读,且有写者等待时,新读者到来后
(1)读者优先:可读
(2)写者优先:等待

下面是代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <getopt.h>

#define N_READER 10
#define N_WRITER 5

/* 
 * 测试文件格式为:
 * R 进程ID 持续时间
 * W 进程ID 持续时间 写入数据
 * 例如:
 * R 1 1
 * W 2 1 1
*/
typedef struct {
	int tid;
	int continueTime;
	int writeData;
}WriterParameter;
typedef struct {
	int tid;
	int continueTime;
}ReaderParameter;

pthread_t readers[N_READER], writers[N_WRITER];
ReaderParameter rp[N_READER];
WriterParameter wp[N_WRITER];
pthread_mutex_t mutex_write, mutex_read;
sem_t sem_read, sem_write;
int data = 0;	// 初始化数据
int readerCnt = 0, writerCnt = 0;

void print_help(char *argv[]) {
	printf("Usage: %s [-rw] -t <file>\n", argv[0]);
	printf("Options:\n");
	printf("  -h         Print this help message.\n");
	printf("  -r         reader first.\n");
	printf("  -w         writer first.\n");
	printf("  -t <file>  test file.\n");
	printf("Examples:\n");
	printf("linux>  %s -r test.txt\n", argv[0]);
}

void write(int writeData) {
    printf("write data: %d to %d\n", data, writeData);
    data = writeData;
}
void read() {
    printf("read data: %d\n",data);
}

// 读者优先(rf)的读者行为
void *reader_rf (void *rp) {
	// 获得写锁的过程不能和其他读者并发,用信号量保护
    sem_wait(&sem_read);
    readerCnt++;
    // 凡是有读者,就获得写锁,后来的写者必须等待。
    if(readerCnt == 1)
        pthread_mutex_lock(&mutex_write);
    sem_post(&sem_read);
    
    // 开始读
    printf("reader %d start reading\n", ((ReaderParameter *)rp)->tid);
    read();
    sleep(((ReaderParameter *)rp)->continueTime);
    printf("reader %d finish reading\n", ((ReaderParameter *)rp)->tid);
    
    sem_wait(&sem_read);
    readerCnt--;
    if(readerCnt == 0)
        pthread_mutex_unlock(&mutex_write);
    sem_post(&sem_read);

    pthread_exit(NULL);
}

// 读者优先(rf)的写者行为
void *writer_rf(void *wp) {
	
	sem_wait(&sem_write);
    writerCnt++;
    if(writerCnt == 1){
        // 凡有写者,就获得读锁,以阻止后来的读者读
        pthread_mutex_lock(&mutex_read);
    }
    sem_post(&sem_write);
	
	// 获得写锁,只有一个写者修改数据
    pthread_mutex_lock(&mutex_write);
    printf("writer %d start writing\n", ((WriterParameter *)wp)->tid);
    write(((WriterParameter *)wp)->writeData);
    sleep(((WriterParameter *)wp)->continueTime);
    printf("writer %d finish writing\n", ((WriterParameter *)wp)->tid);
    pthread_mutex_unlock(&mutex_write);
   
    pthread_exit(NULL);
}

// 写者优先(wf)的读者行为
void *reader_wf (void *rp) {
    // 假如writer锁定了mutex_read,那么其他所有reader被阻塞在这里
    pthread_mutex_lock(&mutex_read);	//只被一个reader占有
    sem_wait(&sem_read);
    readerCnt++;
    if (readerCnt == 1)
        pthread_mutex_lock(&mutex_write);
    sem_post(&sem_read);
    pthread_mutex_unlock(&mutex_read);	// 释放时,写者将优先获得读锁
    
    printf("reader %d start reading\n", ((ReaderParameter *)rp)->tid);
    read();
    sleep(((ReaderParameter *)rp)->continueTime);
    printf("reader %d finish reading\n", ((ReaderParameter *)rp)->tid);

    sem_wait(&sem_read);
    readerCnt--;
    // 最后一个读者读完开始允许写者执行写操作
    if (readerCnt == 0)
        pthread_mutex_unlock(&mutex_write);
    sem_post(&sem_read);

    pthread_exit(NULL);
}

// 写者优先(wf)的写者行为
void *writer_wf(void *wp) {
    sem_wait(&sem_write);
    writerCnt++;
    if(writerCnt == 1){
        // 凡有写者,就获得读锁,以阻止后来的读者读
        pthread_mutex_lock(&mutex_read);
    }
    sem_post(&sem_write);
   
    // 获得写锁,只有一个写者修改数据
    pthread_mutex_lock(&mutex_write);
    printf("writer %d start writing\n", ((WriterParameter *)wp)->tid);
    write(((WriterParameter *)wp)->writeData);
	sleep(((WriterParameter *)wp)->continueTime);
	printf("writer %d finish writing\n", ((WriterParameter *)wp)->tid);
    pthread_mutex_unlock(&mutex_write);
   
    sem_wait(&sem_write);
    writerCnt--;
    //允许后续的读者加入待读队列
    if (writerCnt == 0)
        pthread_mutex_unlock(&mutex_read);
    sem_post(&sem_write);
        
    pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
    pthread_mutex_init(&mutex_write,NULL);
    pthread_mutex_init(&mutex_read,NULL);
    // int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value))
    // pshared为0,表示只能为当前进程的所有线程共享;
    // value为信号量的初始值
    sem_init(&sem_read,0,1);
    sem_init(&sem_write,0,1);
    
    // 函数指针
    // 默认策略为写者优先
    void (*reader) (void *param) = reader_wf;
    void (*writer) (void *param) = writer_wf;
    
    char c;	char *file = NULL;
    while ((c = getopt(argc, argv, "hrwt:")) != -1) {
		switch (c) {
		case 'r':
			reader = reader_rf;
			writer = writer_rf;
			break;
		case 'w':
			break;
		case 't':
			file = optarg;
			break;
		case 'h':
		default:
			print_help(argv);
			return 0;
		}
	}
	
	// 打开测试文件
	FILE *fp = NULL;
	if ((fp = fopen(file, "r")) == NULL) {
		printf("%s: No such file or directory\n", file);
		return 0;
	}
    
    int i = 0, j = 0;	// i和j分别表示读者和写者线程
    // 读取测试文件
    while ((c = fgetc(fp)) != EOF) {
    	char buf[20];
		// 读者
		// 格式为:"R tid continueTIme"
		if (c == 'R') {
			fgetc(fp);	// jump the space
			fgets(buf, 20, fp);
			rp[i].tid = atoi(strtok(buf, " "));
			rp[i].continueTime = atoi(strtok(NULL, " "));
			pthread_t reader_t;
			pthread_create(&readers[i++], NULL, reader, &rp[i++]);
		}
		// 写者
		// 格式为:"R tid continueTIme writeData"
		else {
			fgetc(fp);
			fgets(buf, 20, fp);
			wp[j].tid = atoi(strtok(buf, " "));
			wp[j].continueTime = atoi(strtok(NULL, " "));
			wp[j].writeData = atoi(strtok(NULL, " "));
			pthread_t writer_t;
			pthread_create(&writers[j++], NULL, writer, &wp[j++]);
		}
    }
    sleep(10);
    return 0;
}

下面是我的测试文件:

R 1 2
W 2 1 1
R 3 3
R 4 1
W 5 2 2
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值