操作系统——基于信号量机制的并发程序设计

news2024/10/6 8:36:30

一、实验题目

基于信号量机制的并发程序设计

二、实验目的

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

程序设计。

(2) 了解互斥体对象,利用互斥与同步操作编写读者-写者问题的并发程序,加深对 P (

semWait)V(semSignal)原语以及利用 PV 原语进行进程间同步与互斥操作的理解。

(3) 理解 Linux 支持的信息量机制,利用 IPC 的信号量系统调用编程实现哲学家进餐问题。

三、总体设计(含背景知识或基本原理与算法、模块介绍、设计步骤等)

读者-写者问题:

*在读者-写者问题中,多个读者可以同时读取共享资源,但只能有一个写者可以写入共享资源。

*使用互斥体对象(mutex)实现对共享资源的互斥访问。

*使用信号量(semaphore)实现读者和写者之间的同步和互斥操作。

存在一个多进程共享的数据区,该数据区可以是一个文件或一块内存空间,甚至可以是一组寄存器,有些进程(reader)只读取这个数据区中的数据,有些进程(writer)只往数据区中写数据。此外,还必须满足:

1.任意数量的读进程可同时读这个文件。

2.一次只有一个写进程可以写文件

3.若写进程正在写文件,则禁止任何读进程读文件。

书上实现的读者优先的算法思路是:

写进程比较简单,信号量WriteSemaphore用于实施排斥,只要一个写进程正在访问数据区,其他写进程和读进程就都不能访问它。读进程也使用WriteSemaphore实施互斥,但为了允许多个读进程,没有读进程正在读时,第一个试图读的读进程需要在WriteSemaphore上等待。当至少已有一个读进程在读时,随后的读进程无须等待,可以直接进入。readcount用于记录读进程的数量,信号量XSemaphore用于确保readcount被正确地更新。

四、详细设计(含主要的数据结构、程序流程图、关键代码等)

读者-写者问题的并发程序设计

 

使用互斥体对象mutex来保证对共享资源的互斥访问。

使用两个信号量readers和writers来控制读者和写者之间的同步和互斥操作。

读者线程:

在进入临界区之前,使用sem_wait(&readers)来等待其他读者完成读取操作。

进入临界区读取共享资源。

使用sem_post(&readers)来释放读者信号量。

写者线程:

在进入临界区之前,使用sem_wait(&writers)来等待其他写者完成写入操作。

进入临界区写入共享资源。

使用sem_post(&writers)来释放写者信号量。

代码:

#include <windows.h>

#include <iostream>

#define MAX_READER_NUM 512

#define READER_NUM 3

#define WRITER_NUM 2

#define MOD 100

using namespace std;

int readcount = 0;

HANDLE WriteSemaphore; //实现读写互斥

HANDLE XSemaphore; //对于人数修改的互斥量

DWORD WINAPI reader(LPVOID); //读者线程

DWORD WINAPI writer(LPVOID); //写者线程

bool p_ccontinue = true;    //控制程序结束

int test = 0;

int main()

{

    //初始化两个信号量

    /*结构体指针;信号量对象的初始计数;信号量对象的最大计数;信号量对象的名称*/

    WriteSemaphore = CreateSemaphore(NULL,1,MAX_READER_NUM,NULL);

    XSemaphore = CreateSemaphore(NULL,1,MAX_READER_NUM,NULL);

    //用WindowsAPI模拟课本上 parbegin(reader,writer);

    //总的线程数

    HANDLE hThreads[READER_NUM + WRITER_NUM]; //各线程的 handle

    DWORD readerID[READER_NUM]; //读者线程的标识符

    DWORD writerID[WRITER_NUM]; //写者线程的标识符

    //创建读者线程

    for (int i=0; i<READER_NUM; i++)

    {

        hThreads[i]=CreateThread(NULL,0,reader,NULL,0,&readerID[i]);

        if (hThreads[i]==NULL)

            return -1;

    }

    //创建写者线程

    for (int i=0; i<WRITER_NUM; i++)

    {

        hThreads[READER_NUM+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 READUNIT()

{

    cout<<"一个读者开始阅读:";

    cout<<test<<endl;

}

//写者写

void WRITEUNIT()

{

    cout<<"写者开始写:";

    test = (test+1) % MOD;

    cout<<test<<endl;

}

//读者

DWORD WINAPI reader(LPVOID lpPara)

{

    while(p_ccontinue)

    {

        WaitForSingleObject(XSemaphore,INFINITE); //semWait(x);

        readcount++;

        if(readcount == 1)  //第一个读者来了

            WaitForSingleObject(WriteSemaphore,INFINITE); //semWait(wsem);

        ReleaseSemaphore(XSemaphore,1,NULL); //semSignal(x);

        READUNIT();

        //阅读完毕

        WaitForSingleObject(XSemaphore,INFINITE); //semWait(x);

        readcount--;

        //无读者,释放资源

        if(readcount == 0)

            ReleaseSemaphore(WriteSemaphore,1,NULL); //semSignal(wsem);

        ReleaseSemaphore(XSemaphore,1,NULL); //semSignal(x);

        Sleep(3000);

    }

    return 0;

}

//写者

DWORD WINAPI writer(LPVOID lpPara)

{

    while(p_ccontinue)

    {

        WaitForSingleObject(WriteSemaphore,INFINITE); //semWait(wsem);

        WRITEUNIT();

        ReleaseSemaphore(WriteSemaphore,1,NULL); //semSignal(wsem);

        Sleep(2000);

    }

    return 0;

}

五、实验结果与分析

这段代码的实验结果是模拟了读者和写者对共享资源的并发访问。由于读者和写者之间的同步和互斥操作,读者和写者会交替地对共享资源进行读取和写入操作。通过输出信息可以观察到读者和写者的行为。

值得注意的是,读者和写者之间的调度是不确定的,所以每次运行结果可能略有不同。读者和写者的执行顺序会根据操作系统的调度策略和线程的竞争情况而有所变化。

总体来说,这段代码演示了使用互斥体和信号量来实现读者-写者问题的基本思路和实现方式。通过合理地控制互斥访问和同步操作,可以确保多个读者和写者之间对共享资源的正确访问和修改。

 

六、小结与心得体会

在这个实验中,我们通过使用互斥体对象和信号量机制,成功设计了一个并发程序来解决读者-写者问题。通过这个实验,我得出了以下的小结和心得体会:

1.熟悉操作系统的进程和线程概念:在设计并发程序之前,我们需要对操作系统的进程和线程有一定的了解。了解进程和线程的概念、特点以及它们之间的关系,能够帮助我们更好地理解并发编程的问题和解决方法。

2.理解同步和互斥的重要性:在多个线程同时访问共享资源时,必须确保对共享资源的访问是同步和互斥的。通过使用互斥体对象和信号量,我们可以实现线程之间的同步和互斥操作,避免数据竞争和不一致的结果。

3.学会使用信号量机制:信号量是一种常用的并发编程机制,它可以用来控制并发线程之间的访问和同步。在本实验中,我们使用信号量来控制读者和写者之间的访问和修改共享资源的操作。学会使用信号量的原语,如sem_wait和sem_post,能够有效地实现线程之间的同步和互斥。

4.注意死锁和饥饿问题:在设计并发程序时,需要注意死锁和饥饿问题的可能性。死锁是指多个线程互相等待对方释放资源而无法继续执行的情况,而饥饿则是指某些线程由于资源分配不均而无法得到执行的情况。在本实验中,我们通过合理地设计互斥和同步操作,避免了死锁和饥饿的发生。

5.调试并发程序的挑战:并发程序的调试相对复杂,因为线程的执行顺序是不确定的,可能存在竞争条件和难以重现的错误。在本实验中,我们可以通过输出信息来观察并验证读者和写者的行为,以及共享资源的正确访问和修改。同时,运用调试工具和技巧可以帮助我们更好地理解程序的执行流程和发现潜在的问题。

通过完成这个实验,我对并发程序设计有了更深入的理解。同时,我也意识到在实际开发中,合理地设计并发程序是至关重要的,它涉及到线程之间的协作和资源管理。合理使用同步和互斥机制,能够提高程序的性能、可靠性和正确性,避免出现数据竞争和不一致的结果。并发编程是一项挑战,但也是一项有趣和重要的技能,对于开发高效、可扩展的应用程序至关重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/683845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

测试老鸟,带你手写Python自动化测试 ddt 数据驱动框架(超细细)

前言 python做自动化测试&#xff0c;大多数都应该使用过ddt这个模块&#xff0c;它可以自动根据用例数据&#xff0c;来生成测试用例&#xff0c;能够很方便的将测试数据和测试用例执行的逻辑进行分离。接下来和大家&#xff0c;手把手撸出一个ddt。 DDT的实现原理 首先我们…

MUR80120PT-ASEMI快恢复二极管MUR80120PT

编辑-Z MUR80120PT在TO-247封装里采用的2个芯片&#xff0c;其尺寸都是140MIL&#xff0c;是一款高耐压大电流快恢复二极管。MUR80120PT的浪涌电流Ifsm为600A&#xff0c;漏电流(Ir)为10uA&#xff0c;其工作时耐温度范围为-55~150摄氏度。MUR80120PT采用抗冲击硅芯片材质&…

DJ5-4 MAC、ARP

目录 一、链路层寻址地址 1、MAC 地址分配 2、MAC 地址识别 二、ARP 地址解析协议 1、ARP 地址解析协议 2、ARP&#xff1a;两个主机位于同一个局域网 3、ARP&#xff1a;发送数据报到子网以外 4、ARP 自举 5、ARP 攻击 一、链路层寻址地址 每个节点有网络层地址和链…

模拟电路系列分享-静态工作点

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 例如&#xff1a; 本文主要介绍静态工作点及耦合 整体架构流程 提示&#xff1a;这里可以添加技术整体架构 要想让晶体管对输入电压信号进行有效的放大&#xff0c;必须解…

win10安装配置PostgreSQL

win10安装配置PostgreSQL 1 下载安装PostgreSQL ①进入官网https://www.postgresql.org/&#xff0c;点击页面中心处的download 也可以直接跳过下面的步骤(下面的步骤主要是为了帮助大家了解一般外国软件是如何从官网进入下载页面)&#xff0c;直接进入下载页面&#xff0c;链…

网络安全是个好的专业吗?高考志愿可以选择该专业吗?

首先说说关于学校和就业的问题&#xff0c;提到国内网络安全专业比较好的学校&#xff0c;“四邮四电”&#xff08;北邮、南邮、西邮、重邮、电子科大、西安电子科大、桂林电子科大、杭州电子科大&#xff09;必须拥有姓名。 而从现在的就业形势看&#xff0c;网络安全专业其…

SuperMap GIS基础产品三维GIS FAQ集锦(3)

SuperMap GIS基础产品三维GIS FAQ集锦&#xff08;3&#xff09; 【WebGL】如何批量管理entity图标&#xff0c;同时控制多个图标的显示和隐藏&#xff1f; 【解决办法】使用实体集合CustomDataSource进行管理&#xff0c;将实体按类别分类&#xff0c;分别添加到不同的实体集…

数字 IC 设计职位经典笔/面试题(一)

共100道经典笔试、面试题目&#xff08;文末可全领&#xff09; 什么是同步逻辑和异步逻辑&#xff1f; 同步逻辑是时钟之间有固定的因果关系。异步逻辑是各时钟之间没有固定的因果关系。同步时序逻辑电路的特点&#xff1a;各触发器的时钟端全部连接在一起&#xff0c;并接在…

NAPT之NAT地址池、NAPT之easy-ip、NAT-Server

NAPT之NAT地址池 拓扑 需求 实现企业内网主机&#xff08;PC1-PC4&#xff09;访问公网网站服务器&#xff08;Server1&#xff09; 配置步骤 第一步&#xff1a;给PC1-PC4/Server1配置接口IP地址&#xff0c;掩码&#xff0c;网关 第二步&#xff1a;R1配置默认路由 -边界…

【MySql】用户管理——用户管理|权限管理

文章目录 用户管理用户信息创建用户删除用户修改用户密码 数据库的权限给用户授权回收权限 用户管理 如果我们只能使用root用户&#xff0c;这样存在安全隐患。这时&#xff0c;就需要使用MySQL的用户管理。 比如张三只能操作mytest这个数据库&#xff0c;李四只能操作msg这个…

员工身份管理(EIAM)如何帮助企业降本增效?

随着市场竞争的加剧和经济环境的变化&#xff0c;降本增效成为了现代企业的共同目标。要实现这一目标&#xff0c;企业需要彻底改变传统的生产管理方式&#xff0c;借助数字化技术来实现数据在线、人员在线和行为在线。 数据在线意味着企业的数据可以在多个平台上进行共享、协…

FreeRTOS实时操作系统(七)时间片调度及RTOS的滴答定时器

系列文章目录 FreeRTOS实时操作系统&#xff08;一&#xff09;RTOS的基本概念 FreeRTOS实时操作系统&#xff08;二&#xff09;任务创建与任务删除&#xff08;HAL库&#xff09; FreeRTOS实时操作系统&#xff08;三&#xff09;任务挂起与恢复 FreeRTOS实时操作系统&am…

【Linux】硬件性能测试工具

1、CPU 1.1 stress 1)安装 sudo apt install stress 2)用法 stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 60s3)结果 使用htop查看: 1.2 nbench 1)安装 需要源码编译,源码下载地址 官方(下载很慢):https://www.math.utah.edu/~mayer/linux/bmark.ht…

数据产品-完善DMP系统应该是什么样子的

一、价值定位 首先需要明确DMP系统的价值定位和核心功能&#xff0c;以此才能评估需要涵括哪些内容 ✧用户刻画更清晰&#xff1a;能够通过数据标签化的形式&#xff0c;全面、精准刻画用户全貌 ✧用户触达更精准&#xff1a;能够沉淀不同的策略规则&#xff0c;精准触达不同…

转行做TA(技术美术),需要掌握哪些基础知识?

TA的岗位职责 负责美术与程序之间的沟通&#xff0c;配合实现美术效果&#xff0c;提高画面整体表现力制定美术资源规范&#xff0c;提高导出资源的可用性和规范性快速跟进研发最新的游戏引擎与渲染技术&#xff1b;在性能优化的同时&#xff0c;提高游戏画面表现&#xff1b;…

2023年6月墨天轮中国图数据库排行榜:TGS 开新局,创邻和字节多点突破露锋芒

鸿鹄不坠青云志&#xff0c;鲲鹏展翅九万里。 2023年 墨天轮中国图数据库流行度排行 已经火热出炉&#xff0c;本月中国图数据库排行榜共有31个数据库参与排名&#xff0c;相比今年1月新增3个数据库。本月图数据库榜单前十变动较大&#xff1a;TuGraph 立足创新跃榜首&#xff…

深蓝学院C++基础与深度解析笔记 第 6 章 函数

1. 函数基础 ● 函数&#xff1a;封装了一段代码&#xff0c;可以在一次执行过程中被反复调用。 A、函数头&#xff1a; ● 函数名称 —— 标识符&#xff0c;用于后续的调用 ● 形式参数 —— 代表函数的输入参数 ● 返回类型 —— 函数执行完成后所返回的结果类型 B、函数…

Matplotlib---雷达图

1. 雷达图 fig plt.figure(figsize(6, 6))x np. linspace(0, 2*np.pi, 6, endpointFalse) y [83, 61, 95, 67, 76, 88]# 保证首位相连 x np.concatenate((x, [x[0]])) y np.concatenate((y, [y[0]]))# 雷达图 axes plt.subplot(111, polarTrue) axes.plot(x, y, o-, l…

记录正式环境测试环境【RedHat7编译升级redis7.0.9】--有关报错及解决

记录正式环境&测试环境【RedHat7 编译升级redis7.0.9】--有关报错及解决 &#x1f53b; 一、报错详情1.1 ⛳ 写在前面1.2 ⛳ 报错11.3 ⛳ 报错21.4 ⛳ 安装redis1.5 ⛳ 版本检查 &#x1f53b; 二、⛳ 总结 &#x1f53b; 一、报错详情 1.1 ⛳ 写在前面 &#x1f341; 升级…

甘特图神器大比拼——国内外7款经典工具评测

甘特图是一种重要的项目管理工具&#xff0c;它能够帮助我们规划、安排和跟踪项目的进度和任务。然而&#xff0c;市面上的甘特图工具众多&#xff0c;选择恰当的工具并不容易。在本文中&#xff0c;我们将为您介绍国内外7款经典的甘特图神器&#xff0c;并进行详细评测和比较。…