进程间同步:读者写者问题

下面讲的是读者写者问题中写者优先的实现过程

该问题需要满足:

  1. 读写互斥
  2. 写写互斥
  3. 读读不互斥
  4. 同时有读、写,写优先

需要用到两个全局变量,分别为:

writeCount:写者人数

readCount:读者人数

需要用到5个全局信号量,分别为:

mutex1:目的是控制每次只有一个写者进出写者队列。为1时,写者可以进或出队列,为0时,写者需等待

mutex2:目的是控制每次只有一个读者进出读者队列。为1时,读者可以进或出队列,为0时,读者需等待

mutex3:通过读者的RWMutex比mutex3后申请先释放,使得同种情况下写者比读者先获取RWMutex信号量(实现写者优先)

RWMutex:目的是控制读写互斥。第一个写者需要等待申请RWMutex信号量,以后的写者无需申请直到写者为空释放。而读者每次都需要申请RWMutex信号量,因此会优先写者操作。

wrt:保证每次只有一种类型对文件进行操作(类型1:一个写 类型2:一个读或多个读)

为1时,代表可以对文件进行操作,为0时,代表已有一种类型对文件进行操作。第一个读者需要等待申请wrt信号量,以后的读者无需申请直到读者为空释放。而写者每次都需要申请wrt信号量,因此实现了每次只能有一个写者对文件进行操作,可以有多个读者同时对文件进行操作。

写者的流程:

1.申请mutex1信号量,等待进入写者队列

2.进入队列后writeCount++,若writeCount为1需等待申请RWMutex信号量

3.成功进入写者队列后释放mutex1信号量

4.申请wrt信号量等待写操作

5.进行写操作

6.写入完毕后释放wrt信号量

7.申请mutex1信号量,等待出写者队列

8.出队列后writeCount—,若writeCount为0需释放RWMutex信号量

9.成功出队后释放mutex1信号量

读者的流程:

1.申请mutex3信号,作用是同时等待读者写者,使得写者优先获取RWMutex信号

2.申请RWMutex信号

3.申请mutex2信号,等待进入读者队列

4.进入队列后readCount++,若readCount为1则申请wrt信号量

5.成功进入队列后释放mutex2信号量

6.释放RWMutex信号量

7.释放mutex3信号量

8.进行读操作

9.申请mutex2信号量,等待出读者队列

10.出队列后readCount—,若readCount为0则释放掉wrt信号量

11.成功出队后释放mutex2信号量

举个例子:

/*************************************************************************
	> File Name: p.cpp
	> Author: Zcy
	> Mail: [email protected]
	> Created Time: 三  1/23 18:16:17 2019
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

int readCount, writeCount;
sem_t mutex1, mutex2, mutex3, RWmutex, wrt;

struct node
{
    int num, time1, time2;
};

void init() {
    readCount = 0;
    writeCount = 0;
    sem_init(&mutex1, 0, 1);
    sem_init(&mutex2, 0, 1);
    sem_init(&mutex3, 0, 1);
    sem_init(&RWmutex, 0, 1);
    sem_init(&wrt, 0, 1);
}

void over() {
    sem_destroy(&mutex1);
    sem_destroy(&mutex2);
    sem_destroy(&mutex3);
    sem_destroy(&RWmutex);
    sem_destroy(&wrt);
}

void* read_t(void *t) {
    node *tt = (node *)t;
    sleep(tt -> time1);
    printf("reader %d: start run\n", tt -> num);

    //进读者队列
    sem_wait(&mutex3);
    sem_wait(&RWmutex);
    sem_wait(&mutex2);
    readCount ++;
    if (readCount == 1) {
        sem_wait(&wrt);
    }
    sem_post(&mutex2);
    sem_post(&RWmutex);
    sem_post(&mutex3);

    //读操作
    printf("reader %d: start read\n", tt -> num);
    sleep(tt -> time2);
    printf("reader %d: end read\n", tt -> num);

    //出读者队列
    sem_wait(&mutex2);
    readCount --;
    if (readCount == 0) {
        sem_post(&wrt);
    }
    sem_post(&mutex2);
    pthread_exit(0);
}

void* write_t(void *t) {
    node *tt = (node *)t;
    sleep(tt -> time1);
    printf("writer %d: start run\n", tt -> num);

    //进写者队列
    sem_wait(&mutex1);
    writeCount ++;
    if (writeCount == 1) {
        sem_wait(&RWmutex);
    }
    sem_post(&mutex1);

    //写操作
    sem_wait(&wrt);
    printf("writer %d: start write\n", tt -> num);
    sleep(tt -> time2);
    printf("writer %d: end write\n", tt -> num);
    sem_post(&wrt);

    //出写者队列
    sem_wait(&mutex1);
    writeCount --;
    if (writeCount == 0) {
        sem_post(&RWmutex);
    }
    sem_post(&mutex1);
    pthread_exit(0);
}
 
int main () {
    int num = 0;
    pthread_t pid;
    pthread_attr_t attr;

    pthread_attr_init(&attr);
    init();

    while(scanf("%d", &num) != EOF) {
        char chooes;
        int time1, time2;
        scanf("%c%d%d", &chooes, &time1, &time2);
        node *t = (node *)malloc(sizeof(node));
        t -> num = num;
        t -> time1 = time1;
        t -> time2 = time2;
        if (chooes == 'R') {
            printf("reader %d: start waiting\n", num);
            pthread_create(&pid, &attr, read_t, t);
        } else if(chooes == 'W') {
            printf("writer %d: start waiting\n", num);
            pthread_create(&pid, &attr, write_t, t);
        }
    }
    over();
    return 0;
}

此时结果为:

reader 1: start waiting
writer 2: start waiting
reader 3: start waiting
reader 4: start waiting
writer 5: start waiting
reader 1: start run
reader 1: start read
writer 2: start run
reader 3: start run
reader 4: start run
writer 5: start run
reader 1: end read
writer 2: start write
writer 2: end write
writer 5: start write
writer 5: end write
reader 3: start read
reader 4: start read
reader 3: end read
reader 4: end read

转载请注明出处!!!

如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢

猜你喜欢

转载自blog.csdn.net/Ivan_zcy/article/details/88070766