【读者-写者问题】基于信号量机制的并发程序设计

一、实验目的

1、回顾操作系统进程、线程的有关概念,针对经典的同步、互斥、死锁与饥饿问题进行并发程序设计。

2、了解互斥体对象,利用互斥与同步操作编写读者-写者问题的并发程序,加深对P、V原语以及利用P、V原语进行进程间同步与互斥操作的理解。

二、基本原理

1、CreateSemaphore()函数,其参数含义分别为:

        ①定义信号量的安全特性        ②信号量的初始计数

        ③信号量的最大计数            ④信号量对象的名称

2、CreateThread()函数,其参数含义分别为:

        ①定义信号量的安全特性        ②初始栈的大小

        ③指向线程函数的指针          ④向线程函数传递的参数

        ⑤线程标志                    ⑥保存新线程的ID

3、WaitForSingleObject()函数,其参数含义分别为:

        ①对象句柄(可指定一系列对象)  ②定时时间间隔

4、ReleaseSemaphore()函数,参数含义为所要操作的信号量对象的句柄。

三、模块介绍

1、main()函数模块:初始化读者和写者的信息并创建线程;

2、Read()函数模块:读者阅读;

3、Write()函数模块:写者写入;

4、Leave()函数模块:读者/写者离开;

5、Reader()函数模块:读者线程执行互斥访问操作;

6、Writer()函数模块:写者线程执行互斥访问操作。

四、流程图

五、代码实现

#include<iostream>
#include<Windows.h>
using namespace std;

unsigned short writerID = 1;                                                        //写者的ID
int readcount = 0;						                                            //记录读者的数量
bool p_ccontinue = true;				                                            //控制程序结束
HANDLE x;								                                            //确保readcount被正确地更新
HANDLE wsem;							                                            //实现读进程(写进程)的互斥
DWORD WINAPI Reader(LPVOID);			                                            //读者线程
DWORD WINAPI Writer(LPVOID);			                                            //写者线程

int main() {
	const unsigned short READERS_COUNT = 3;                                         //读者总数
	const unsigned short WRITERS_COUNT = 2;                                         //写者总数
	const unsigned short THREADS_COUNT = READERS_COUNT + WRITERS_COUNT;             //线程总数
	HANDLE hThreads[THREADS_COUNT];                                                 //各线程的handle
	DWORD ReaderID[READERS_COUNT];                                                  //读者线程的标识符
	DWORD WriterID[WRITERS_COUNT];                                                  //写者线程的标识符
    wsem = CreateSemaphore(NULL, 1, READERS_COUNT, NULL);
    x = CreateSemaphore(NULL, 1, READERS_COUNT, NULL);
    for (int i = 0; i < READERS_COUNT; ++i) {                                       //创建读者线程
        hThreads[i] = CreateThread(NULL, 0, Reader, NULL, 0, &ReaderID[i]);
        if (hThreads[i] == NULL)
            return -1;
    }
    for (int i = 0; i < WRITERS_COUNT; ++i) {                                       //创建写者进程
        hThreads[WRITERS_COUNT + i] = CreateThread(NULL, 0, Writer, NULL, 0, &WriterID[i]);
        if (hThreads[i] == NULL)
            return -1;
    }
    while (p_ccontinue)
        if (getchar())                                                              //按回车后终止程序运行
            p_ccontinue = false;
    return 0;
}

void Read() { cout << "Readers start reading..." << endl; }                         //读者开始阅读

void Write() { cout << "Writers " << writerID++ << " start writing..." << endl; }   //写者开始写入

void Leave() { cout << "leaving..." << endl; }                                      //离开

DWORD WINAPI Reader(LPVOID lpPara) {	                                            //读者
    while (p_ccontinue) {
        WaitForSingleObject(x, INFINITE);                                           //semwait(x)[INFINITE:对象被触发信号后函数返回]
        readcount++;
        if (readcount == 1)
            WaitForSingleObject(wsem, INFINITE);                                    //semwait(wesm)[INFINITE:对象被触发信号后函数返回]
        ReleaseSemaphore(x, 1, NULL);                                               //semsignal(x)
        Read();
        Sleep(2500);
        WaitForSingleObject(x, INFINITE);                                           //semwait(x)[INFINITE:对象被触发信号后函数返回]
        Leave();
        readcount--;
        if (readcount == 0)
            ReleaseSemaphore(wsem, 1, NULL);                                        //semsignal(wsem)
        ReleaseSemaphore(x, 1, NULL);                                               //semsignal(x)
    }
	return 0;
}

DWORD WINAPI Writer(LPVOID lpPara) {	                                            //写者
    while (p_ccontinue) {
        WaitForSingleObject(wsem, INFINITE);                                        //semwait(wesm)                          
        Write();
        Sleep(1500);
        Leave();
        ReleaseSemaphore(wsem, 1, NULL);                                            //semsignal(wsem)
    }
	return 0;
}

六、实验结果与分析

        运行结果如下

        本实验选择读者优先的策略,首先前三个读者依次申请进行读取操作,其中第一个读者申请后执行semwait(wsem),禁止写者进行写入操作,此后读者读取数据。当第三个读者离开时执行semsignal(wsem),允许写者进行写入操作;当第一个写者成功申请进行写入操作时执行semwait(wsem),禁止读者和其他写者进行操作,当第一个写者离开时执行semsignal(wsem),允许读者和其他写者进行操作,以此类推。

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

有为肥宅

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

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

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

打赏作者

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

抵扣说明:

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

余额充值