操作系统课程设计----读者-写者 问题(c语言)

问题描述:

所谓读者写着问题,是指保证一个writer进程必须与其他进程互斥地访问共享对象的同步问题。读者写者问题可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是,只能有一个写者在写书。为实现读写同步,需要使用信号量机制。信号量机制是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者则是这一机制的一个经典范例。

对利用信号量来解决读者—写者问题的描述如下:

1)写-写互斥,即不能有两个写者同时进行写操作;
2)读-写互斥,即不能同时有一个读者在读,同时却有一个写者在写;
3)读读允许,即可以有2个以上的读者同时读。

课设要求:

本次课程设计中,在处理读者写者等待队列的请求时,用到了两种唤醒进程算法:读者优先唤醒算法和写者优先唤醒算法。

读优先:当一个读者与若干写者同时处于等待队列中时,并且此时并无写操作进行时,读者优先进行读。
写优先:当一个读者与若干写者同时处于等待队列中时,并且此时并无写操作进行时,写者优先进行写。

主要数据结构:

typedef struct
{
int id;
char name[256];
int operateTime;
int flag;//1为读者,2为写者
}runQueue;//进行中队列结构;

typedef struct
{
int id;
char name[256];
int operatetime;
int flag;//1为读等待,2为写等待
}wait;//等待队列结构;

个人思路:

创建两个队列,一个队列用于存储进行中的进程;一个队列用于存储等待中的进程。当创建读者进程或写者进程时,查看当前进行中队列是否已满,若已满则进入等待者队列。当一个进程结束时,查看其是否占用队列最后一位,若是则等待中队列进程可进入进行中队列。在单个进程对队列操作时,对队列使用p操作,结束后使用v操作释放。

环境:

编译器:codeblocks20.03
c语言:c11
操作系统:windows10

代码:

主函数以及各定义

#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <string.h>

typedef struct
{
int id;
char name[256];
int operateTime;
int flag;//1为读者,2为写者
}runQueue;//进行中队列结构;


typedef struct
{
int id;
char name[256];
int operatetime;
int flag;//1为读等待,2为写等待
}wait;//等待队列结构;

int id = 0;//全局变量id
int waitqLen=0,runqLen=0;     //全局变量三个队列的长度
int waitqNLen=0,runqNLen=0;  //全局变量三个队列目前的长度
int nowThread = 0;//目前线程数
int operating1 = 0,operating2 = 0;//正在对队列操作的进程
wait waitQueue[1000]={};   //等待者队列
runQueue runningQueue[1000]={};//进行中队列

void showQueue();//展示目前队列情况
void creatReader();//创建读者
void creatWriter();//创建写者
void readerThread();//读者线程
void writerThread();//写者线程
void WaitToRun();//等待队列进入进行中队列(读者优先)
void WaitToRunWFirst()//等待队列进入进行中队列(写者优先)
void runWaitToRun();//进入队列线程开启
void AreaderThread();//单个读者线程
void AwriterThread();//单个写者线程







int main()
{

 printf("请输入等待队列长度:");
 scanf("%d",&waitqLen);
 printf("请输入进行中队列长度:");
 scanf("%d",&runqLen);

 int Choice = 0;
 while(1)
 {
     Choice=0;
     printf("1.查看当前队列情况\n");
     printf("2.创建读者\n");
     printf("3.创建写者\n");
     printf("4.退出\n");
     printf("请输入操作项:");
     scanf("%d",&Choice);
     switch(Choice)
        {
        case 1:
            showQueue();
            break;
        case 2:
            creatReader();
            break;
        case 3:
            creatWriter();
            break;
        case 4:
            return 0;
            break;
        }

 }


}


展示目前队列



void showQueue()
{
    printf("\n/****---------------------****/\n");
    printf("当前进程数:%d\n\n",nowThread);
    printf("等待者队列:\n");
    for(int i=1;i<=waitqNLen;i++)
    {
        printf("/**\n等待者id:%d\n",waitQueue[i].id);
        printf("等待者名:%s\n",waitQueue[i].name);
        if(waitQueue[i].flag==1)
        printf("等待者类型:读者\n");
        else
        printf("等待者类型:写者\n");
        printf("等待者操作时间:%ds\n**/\n",waitQueue[i].operatetime);
    }
    printf("---------------------\n");
    printf("进行中队列:\n");
    for(int i=1;i<=runqNLen;i++)
    {
        if(runningQueue[i].flag==1)
        {
            printf("/**\n读者id:%d\n",runningQueue[i].id);
            printf("读者名:%s\n**/\n",runningQueue[i].name);
        }
        else
        {
            printf("/**\n写者id:%d\n",runningQueue[i].id);
            printf("写者名:%s\n**/\n",runningQueue[i].name);
        }

    }

    printf("\n/****---------------------****/\n\n");
}

创建读者、写者

void creatReader()
{

    if(runqNLen == runqLen || runningQueue[0].flag==2)
    {
        printf("当前进行中队列已满,进入等待队列。\n");
        if(waitqNLen == waitqLen)
        {
            printf("等待队列已满,入队失败!\n");

        }
        else
        {
            id++;
            waitqNLen++;
            waitQueue[waitqNLen].id=id;
            printf("请输入读者名:");
            scanf("%s",waitQueue[waitqNLen].name);
            waitQueue[waitqNLen].flag=1;
            printf("请输入读时间:");
            scanf("%d",&waitQueue[waitqNLen].operatetime);
            printf("已进入等待队列。\n");
            return 0;
        }
     return 0;
    }
    else
    {
        id++;
        int readtime=0;
        runqNLen++;
        runningQueue[runqNLen].id=id;
        printf("请输入读者名:");
        scanf("%s",runningQueue[runqNLen].name);
        runningQueue[runqNLen].flag = 1;
        printf("请输入阅读时间(单位:秒):");
        scanf("%d",&readtime);
        runningQueue[runqNLen].operateTime=readtime;
        printf("开启读者线程成功,读者id:%d,读者名称%s\n",id,runningQueue[runqNLen].name);
        _beginthread(readerThread,0,NULL);
        nowThread++;
    }


}



void creatWriter()
{
    if(runqNLen != 0)
    {
        printf("当前进行中队列已满,进入等待队列。\n");
        if(waitqNLen == waitqLen)
        {
            printf("等待队列已满,入队失败!\n");

        }
        else
        {
            id++;
            waitqNLen++;
            waitQueue[waitqNLen].id=id;
            printf("请输入读者名:");
            scanf("%s",waitQueue[waitqNLen].name);
            waitQueue[waitqNLen].flag=2;
            printf("请输入读时间:");
            scanf("%d",&waitQueue[waitqNLen].operatetime);
            printf("已进入等待队列。\n");
            return 0;
        }
     return 0;
    }
    else
    {
        id++;
        int readtime=0;
        runqNLen++;
        runningQueue[runqNLen].id=id;
        printf("请输入写者名:");
        scanf("%s",runningQueue[runqNLen].name);
        runningQueue[runqNLen].flag = 2;
        printf("请输入写作时间(单位:秒):");
        scanf("%d",&readtime);
        runningQueue[runqNLen].operateTime=readtime;
        printf("开启写者线程成功,写者id:%d,写者名称%s\n",id,runningQueue[runqNLen].name);
        _beginthread(writerThread,0,NULL);
        nowThread++;
    }

}

等待队列进入/读者优先/


void WaitToRun()
{
    if(waitqNLen==0)
        return 0;
    else
    {
     while(1)
        {
             if(operating1==0)
             break;
             Sleep(200);
        }
        operating1=1;
        for(int i = 1;i<=waitqNLen;i++)
        {
            if(waitQueue[i].flag == 1)
            {
              while(1)
              {
                 if(operating2==0)
                 break;
                 Sleep(200);
              }
            operating2=1;
            runqNLen++;
            runningQueue[runqNLen].flag=waitQueue[i].flag;
            runningQueue[runqNLen].id=waitQueue[i].id;
            strcpy(runningQueue[runqNLen].name,waitQueue[i].name);
            runningQueue[runqNLen].operateTime=waitQueue[i].operatetime;
            printf("开启读者线程成功,读者id:%d,读者名称%s\n",runningQueue[runqNLen].id,runningQueue[runqNLen].name);
            _beginthread(AreaderThread,0,NULL);
            operating2=0;


            for(int j = i;j<=waitqNLen;j++)
            {
                waitQueue[j]=waitQueue[j+1];
            }
            waitqNLen--;
            operating1=0;
            return 0;
            }
            operating1=0;

            if(i==waitqNLen&&runqNLen==0)
            {
                 while(1)
                {
                     if(operating1==0)
                     break;
                     Sleep(200);
                }
                operating1=1;
                for(i=1;i<=waitqNLen;i++)
                {

                    if(waitQueue[i].flag == 2)
                    {
                      while(1)
                      {
                         if(operating2==0)
                         break;
                         Sleep(200);
                      }
                    operating2=1;

                    runqNLen++;
                    runningQueue[runqNLen].flag=waitQueue[i].flag;
                    runningQueue[runqNLen].id=waitQueue[i].id;
                    strcpy(runningQueue[runqNLen].name,waitQueue[i].name);
                    runningQueue[runqNLen].operateTime=waitQueue[i].operatetime;
                    printf("开启写者线程成功,写者id:%d,写者名称%s\n",runningQueue[runqNLen].id,runningQueue[runqNLen].name);
                    _beginthread(AwriterThread,0,NULL);
                    operating2=0;

                     for(int j = i;j<=waitqNLen;j++)
                     {
                        waitQueue[j]=waitQueue[j+1];
                     }
                     waitqNLen--;
                      operating1=0;
                      return 0;

                    }
                }
                operating1=0;
                return 0;
                }
        }
    }




}

等待队列进入/写者优先/


/*写者优先*/
void WaitToRunWFirst()
{
    if (waitqNLen == 0)
        return 0;
    else
    {
        while (1)
        {
            if (operating1 == 0)
                break;
            Sleep(200);
        }
        operating1 = 1;
        for (int i = 1; i <= waitqNLen; i++)
        {
            if (waitQueue[i].flag == 2)
            {
                while (1)
                {
                    if (operating2 == 0)
                        break;
                    Sleep(200);
                }
                operating2 = 1;
                runqNLen++;
                runningQueue[runqNLen].flag = waitQueue[i].flag;
                runningQueue[runqNLen].id = waitQueue[i].id;
                strcpy(runningQueue[runqNLen].name, waitQueue[i].name);
                runningQueue[runqNLen].operateTime = waitQueue[i].operatetime;
                printf("开启读者线程成功,读者id:%d,读者名称%s\n", runningQueue[runqNLen].id, runningQueue[runqNLen].name);
                _beginthread(AreaderThread, 0, NULL);
                operating2 = 0;


                for (int j = i; j <= waitqNLen; j++)
                {
                    waitQueue[j] = waitQueue[j + 1];
                }
                waitqNLen--;
                operating1 = 0;
                return 0;
            }
            operating1 = 0;

            if (i == waitqNLen)
            {
                while (1)
                {
                    if (operating1 == 0)
                        break;
                    Sleep(200);
                }
                operating1 = 1;
                for (i = 1; i <= waitqNLen; i++)
                {

                    if (waitQueue[i].flag == 1)
                    {
                        while (1)
                        {
                            if (operating2 == 0)
                                break;
                            Sleep(200);
                        }
                        operating2 = 1;

                        runqNLen++;
                        runningQueue[runqNLen].flag = waitQueue[i].flag;
                        runningQueue[runqNLen].id = waitQueue[i].id;
                        strcpy(runningQueue[runqNLen].name, waitQueue[i].name);
                        runningQueue[runqNLen].operateTime = waitQueue[i].operatetime;
                        printf("开启写者线程成功,写者id:%d,写者名称%s\n", runningQueue[runqNLen].id, runningQueue[runqNLen].name);
                        _beginthread(AwriterThread, 0, NULL);
                        operating2 = 0;

                        for (int j = i; j <= waitqNLen; j++)
                        {
                            waitQueue[j] = waitQueue[j + 1];
                        }
                        waitqNLen--;
                        operating1 = 0;
                        return 0;

                    }
                }
                operating1 = 0;
                return 0;
            }
        }
    }




}


进程的内操作



void AreaderThread()
{
    nowThread++;
    int threadID=runningQueue[runqNLen].id;
    Sleep(1000*runningQueue[runqNLen].operateTime);
      while(1)//当有线程在操作队列时等待其操作结束才能开始操作
    {
     if(operating2==0)
     break;
     Sleep(200);
    }
    operating2=1;
    for(int i=1;i<=runqNLen;i++)
    {
        if(runningQueue[i].id==threadID)
        {
            printf("\n读者线程结束,读者id:%d,读者名称:%s\n",runningQueue[i].id,runningQueue[i].name);
            for(int j = i;j<=runqNLen;j++)
            {
                runningQueue[j]=runningQueue[j+1];
            }
            runqNLen--;
            break;
        }
    }
    operating2=0;
    
    WaitToRun();


    nowThread--;
    _endthread();

}





void AwriterThread()//单个写者线程
{
    nowThread++;
    int threadID=runningQueue[runqNLen].id;
    Sleep(1000*runningQueue[runqNLen].operateTime);
      while(1)//当有线程在操作队列时等待其操作结束才能开始操作
    {
     if(operating2==0)
     break;
     Sleep(200);
    }
    operating2=1;
    for(int i=1;i<=runqNLen;i++)
    {
        if(runningQueue[i].id==threadID)
        {
            printf("\n写者线程结束,写者id:%d,写者名称:%s\n",runningQueue[i].id,runningQueue[i].name);
            for(int j = i;j<=runqNLen;j++)
            {
                runningQueue[j]=runningQueue[j+1];
            }
            runqNLen--;
            break;
        }
    }
    operating2=0;
    nowThread--;
    
    WaitToRun();
    _endthread();
}



void writerThread()
{
  int threadID=id;
  Sleep(1000*runningQueue[runqNLen].operateTime);
  while(1)//当有线程在操作队列时等待其操作结束才能开始操作
  {
     if(operating2==0)
     break;
     Sleep(200);
  }
  operating2=1;
    for(int i=1;i<=runqNLen;i++)
    {
        if(runningQueue[i].id==threadID)
        {
            printf("\n写者线程结束,写者id:%d,写者名称:%s\n",runningQueue[i].id,runningQueue[i].name);
            for(int j = i;j<=runqNLen;j++)
            {
                runningQueue[j]=runningQueue[j+1];
            }
            runqNLen--;
            break;
        }
    }
  operating2=0;
  nowThread--;
 
  WaitToRun();
  _endthread();


}


void readerThread()
{
  int threadID=id;
  Sleep(1000*runningQueue[runqNLen].operateTime);
  while(1)
  {
     if(operating2==0)
     break;
     Sleep(200);
  }
  operating2=1;
  for(int i=1;i<=runqNLen;i++)
  {
      if(runningQueue[i].id==threadID)
      {
          printf("\n读者线程结束,读者id:%d,读者名称:%s\n",runningQueue[i].id,runningQueue[i].name);
          for(int j = i;j<=runqNLen;j++)
          {
              runningQueue[j]=runningQueue[j+1];
          }
          runqNLen--;
          break;
      }
  }
  operating2=0;
  nowThread--;
  
  WaitToRun();

  _endthread();


}

  • 9
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
大一C语言图书管理系统课程设计是一个模拟图书管理系统的项目,主要包括图书的库存信息、每本书的借阅信息以及每个人的借书信息。这个项目的目标是通过编程实现一个简单的图书管理系统,让学生能够练习和应用C语言的知识。 在这个项目中,你需要设计和实现以下功能: 1. 图书库存:包括添加书、删除图书、修改图书信息操作。 2.书管理:包括借书、还书、查询借阅信息等操作。 3. 读者管理:包括添加读者读者、修改读者信息等操作。 4. 数据存储:使用文件或数据库来存储图书、借阅和读者信息。 你可以根据自己的需求和能力来设计和实现这个图书管理系统。可以使用C语言的基本语法、控制结构、函数、数组等知识来完成这个项目。你可以使用结构体来表示图书、借阅和读者信息,并使用文件操作或数据库操作来实现数据的存储和读取。 以下是一个简单的示例代码,用于演示如何实现图书管理系统的一部分功能: ```c #include <stdio.h> #include <stdlib.h> // 定义图书结构体 typedef struct { char title[100]; char author[100]; int quantity; } Book; // 添加图书 void addBook(Book *books, int *count) { printf("Enter book title: "); scanf("%s", books[*count].title); printf("Enter book author: "); scanf("%s", books[*count].author); printf("Enter book quantity: "); scanf("%d", &books[*count].quantity); (*count)++; printf("Book added successfully.\n"); } // 显示图书列表 void displayBooks(Book *books, int count) { printf("Book List:\n"); for (int i = 0; i < count; i++) { printf("Title: %s, Author: %s, Quantity: %d\n", books[i].title, books[i].author, books[i].quantity); } } int main() { Book books[100]; int count = 0; int choice; do { printf("1. Add book\n"); printf("2. Display books\n"); printf("0. Exit\n"); printf("Enter your choice: "); scanf("%d", &choice); switch (choice) { case 1: addBook(books, &count); break; case 2: displayBooks(books, count); break; case 0: printf("Exiting...\n"); break; default: printf("Invalid choice. Please try again.\n"); } } while (choice != 0); return 0; } ``` 这是一个简单的图书管理系统的示例代码,其中包括添加图书和显示图书列表的功能。你可以根据需要扩展和修改这个代码,实现更多的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Anihaliation

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值