操作系统之多线程编程—读者优先写者优先详解

操作系统之进程调度——优先权法和轮转法(附上样例讲解) 操作系统之银行家算法—详解流程及案例数据 操作系统之多线程编程—读者优先写者优先详解 操作系统之存储管理——FIFO算法和LRU算法 操作

操作系统之进程调度——优先权法和轮转法(附上样例讲解)
操作系统之银行家算法—详解流程及案例数据
操作系统之多线程编程—读者优先/写者优先详解
操作系统之存储管理——FIFO算法和LRU算法
操作系统之磁盘调度——SCAN实例讲解

要求

一、实验目的
1、熟悉多线程编程
2、熟悉使用信号量机制解决进程同步问题
二、实验内容
创建一个包含n 个线程的控制台进程。用这n 个线程来表示n个读者或写者。每个线程按相应测试数据文件的要求,进行读写操作。请用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者优先:如果一个读者申请进行读操作时已有另一读者正在进行读操作,则该读者可直接开始读操作。
写者优先:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
三、实验条件
1、为每个学生提供一台具有WINDOWS 2000/NT/XP操作系统的计算机;
2、实验机器要求安装Visual C 6.0编程平台;
3、实验要求一人一机。
四、 运行结果显示要求
1、要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。
2、测试数据文件格式:测试数据文件包括n 行测试数据,分别描述创建的n 个线程是读者还是写者,以及读写操作的开始时间和持续时间。每行测试数据包括四个字段,各字段间用空格分隔。第一字段为一个正整数,表示线程序号。第二字段表示相应线程角色,R 表示读者是,W 表示写者。第三字段为一个正数,表示读写操作的开始时间。线程创建后,延时相应时间(单位为秒)后发出对共享资源的读写申请。第四字段为一个正数,表示读写操作的持续时间。当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。下面是一个测试数据文件的例子:
1 R 3 5
2 W 4 5
3 R 5 2
4 R 6 5

理解

上面是实验要求。下面讲讲自己的体会:

  • 首先要明白在多线程编程中的互斥关系——读写互斥写写互斥。两个优先方式都遵从这个出发点。
  • 在满足以上的条件下,进来的线程都好像是在排队,然后看当前谁优先。
  • 自己如果是优先的,那么可以直接插队。再考虑正在执行的是否和自己阻塞,如果正在执行的和自己阻塞,那自己也得排队,只不过排在前面。(类似写者优先的写写线程)如果正在执行的和自己不是阻塞的,那么自己就可以直接进去执行(读者优先的读读进程)。
  • 如果自己不是优先的,那么自己只能老老实实的排队,就算自己前面有和自己不互斥的线程执行也不行。类似写者优先的(读线程在执行,新的写进程等待资源,更新的读线程只能等写进程释放,如果有新的写进程进来,还可以插队,——他只能等待队列中所有在等待的写进程释放完毕再执行自己。)
  • 对于读者优先

读者就是优先的。假设a,b都是同时请求,但是a是读者那么a优先使用资源,还有一点很重要的就是读者优先的读者可以并行执行。而写着只能单线程执行。在执行过程中,只要阻塞的写者在等待过程中有新的读者进来那么他要等待所有读者完成才能自己释放自己。

  • 对于写者优先

无疑所有写的操作是优先的,这个过程可能会产生大量阻塞,因为相对较快(本来可以并行的读者被大量阻塞)。如果资源中没有写者那么读者依然可以并行,但是一旦出现写者在等待读者资源,那么新的读者就不能在并行执行,要等待所有写者执行完毕才可执行读者。

对于多线程编程的注意点有:

  1. 读者优先和写者优先是两个不同的策略方法,方法有相似之处但是也有很大不同,函数需要分开完成。
  2. 最主要的排序方式基于时间排序,次要的排序以读者还是写者谁优先为准则
  3. 读者优先或者写者优先的阻塞会导致线程开始时间的变化。而不过采用双队列一个存进入时间的排序,一个存结束时间的排序,修改其中的一个会影响另一个队列中元素值不错,但是如果不对另一个队列进行增/删不会触发堆排序的功能(挺重要的)。
  4. 可能有些阻塞时候的等待时间和开始时间改变处理比较复杂,要考虑当前是读致使阻塞,还是写致使阻塞,还是前面有写的资源再等待致使阻塞。要用多个变量维系系统使得正确的更改线程的阻塞时间。

我的大体思路(水平有限,不一定很准确):

代码

下面附上我的ac代码

package 实验;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

public class morethread {

	static Scanner sc=new Scanner(System.in);
	static Queue<thread>q1;
	static Queue<thread>end;
	static thread thread[];
	static int time=0;
	private static void threadcreate(int n) {//创建线程
		thread=new thread[n];
		for(int i=0;i<n;i++) {
		System.out.println("请输入线程"+(i+1)+"的相关属性(id,r/w,intime,timelong)");
		int id=sc.nextInt();
		String type=sc.next();
		int start=sc.nextInt();
		int chixu=sc.nextInt();
		thread [i]=new thread(id, type, start, chixu);
		System.out.println("线程"+id+"  操作:"+type+"  开始时间:"+start+"   持续时间:"+chixu);
		}
	}
	private static void writerthread(int n) {//写者优先
		// TODO 自动生成的方法存根
		q1=new PriorityQueue<thread>(comstart2);
		end=new PriorityQueue<thread>(comend);
		for(int i=0;i<n;i++)
		{
           q1.add(thread[i]);
           end.add(thread[i]);
		}
		int timeend=-1;//读结束的时间最晚
		int writendtime=0;//写操作结束的时间
		thread start=q1.peek();thread finish=end.peek();
		boolean iswait=false;//是否有write操作在等待
		while(!q1.isEmpty()||!end.isEmpty())
		{
			if(!q1.isEmpty()) {start=q1.peek();}
			if(!end.isEmpty()) {finish=end.peek();}
			if(start.starttime<(finish.starttime+finish.totaltime)&&!q1.isEmpty())//可以开始读写操作
			{
				thread team=q1.poll();
				if(team.type.equals("w"))//写操作
				{
					if(team.starttime>=writendtime)//没有写操作在前面
					{
						if(team.starttime<timeend)//需要等待 更改改点信息重新pull入队列
						{
							iswait=true;//声明之后其他读操作就不能再直接进行
							team.starttime=timeend;
							q1.add(team);
							end.remove(team);end.add(team);
						}
						else {//不需要等待,直接开始
							System.out.println("线程"+team.id+" 开始:"+team.type+"操作  时间:"+team.starttime+"  结束时间"+(team.starttime+team.totaltime));
							writendtime=team.starttime+team.totaltime;//更新写操作的结束时间
							
							iswait=false;//更新等待点
						}
					}
					else//有正在进行的操作,需要等待
					{
						iswait=true;
						team.starttime=writendtime;
						q1.add(team);
						end.remove(team);end.add(team);//移除然后增加才可以重新排序
					}
				}
				else//读操作
				{
					if(iswait)
					{//不清楚他在等待读操作还是写操作,反正它一定不能在下面两个操作之前完成,所以更新节点道值最大的
						int time2=timeend;
						if(time2<writendtime)time2=writendtime;
						team.starttime=time2;
						q1.add(team);
						end.remove(team);end.add(team);
					}
					else//没有等待点
					{
						if(team.starttime<writendtime)//有写操作,读需要等待 将这个点从新弄道队列里面
						{
							team.starttime=writendtime;
							q1.add(team);
							end.remove(team);end.add(team);
						}
						else//可以释放了
						{
						System.out.println("线程"+team.id+" 开始:"+team.type+"操作  时间:"+team.starttime+"  结束时间"+(team.starttime+team.totaltime));	
						if(team.starttime+team.totaltime>timeend)//如果可以更新时间
						{
							timeend=team.starttime+team.totaltime;
						}
						}
					}
				}				
			}	
			else
			{
				thread team=end.poll();
				System.out.println("线程"+team.id+" 结束:"+team.type+" 结束时间"+(team.starttime+team.totaltime));
			}
		}
		
	}
	private static void readerthread(int n)//读者优先
	{
		q1=new PriorityQueue<thread>(comstart);
		end=new PriorityQueue<thread>(comend);
		for(int i=0;i<n;i++)
		{
           q1.add(thread[i]);
           end.add(thread[i]);
		}
		int timeend=-1;//读结束的时间最晚
		int writendtime=0;//写操作结束的时间,如果有写的状态,那么
		thread start=q1.peek();thread finish=end.peek();
		while(!q1.isEmpty()||!end.isEmpty())
		{
			if(!q1.isEmpty()) {start=q1.peek();}
			if(!end.isEmpty()) {finish=end.peek();}
			if(start.starttime<=(finish.starttime+finish.totaltime)&&!q1.isEmpty())//可以开始读写操作
			{
				thread team=q1.poll();
				if(writendtime>start.starttime)//此时有写的情况,需要等待阻塞,也就是将此队列头抛出修改开始时间然后再次入队
				{
					team.starttime=writendtime;
					q1.add(team);
					end.remove(team);end.add(team);
				}
				else {//此时无写的操作,无操作或者读操作
					//System.out.println("线程"+team.id+" 开始:"+team.type+"操作  时间:"+team.starttime+"  结束时间"+(team.starttime+team.totaltime));
					if(team.type.equals("w"))//写的情况,写需要检查是否阻塞自己如果有读的情况则需要阻塞自己
					{
						int time2=timeend;
						if(time2<writendtime)time2=writendtime;
						if(team.starttime>=time2)//在这个时间前没有任何读或者写的操作,上锁,等于号一定有,因为都抛出它了,他的优先级一定最高
						{
							
							writendtime=team.starttime+team.totaltime;
							System.out.println("线程"+team.id+" 开始:"+team.type+"操作  时间:"+team.starttime+"  结束时间"+(team.starttime+team.totaltime));
						}
						else {//状态还有读操作,需要阻塞
							team.starttime=time2;
							q1.add(team);
							end.remove(team);end.add(team);
						}
					}
					else//读的情况
					{
						System.out.println("线程"+team.id+" 开始:"+team.type+"操作  时间:"+team.starttime+"  结束时间"+(team.starttime+team.totaltime));
						if(team.starttime+team.totaltime>timeend)
						{
							timeend=team.starttime+team.totaltime;
						}
					}
				}
			}
			else if(!end.isEmpty()){//某个结束操作在这个时间段
				thread team=end.poll();
				System.out.println("线程"+team.id+" 结束:"+team.type+" 结束时间"+(team.starttime+team.totaltime));
				
			}
		}
	}
	public static void main(String[] args) {
		System.out.println("请输入n个线程程序");		
		int n=sc.nextInt();
		threadcreate(n);
		System.out.println("请输入数字选择读者优先或者写者优先\n1:读者优先\n2:写者优先");
		int index=sc.nextInt();
		while(index<1||index>2) {System.out.println("请输入正确的数字");index=sc.nextInt();}
		if(index==1)//读者优先
		{
			readerthread(n);
		}
		else {
			writerthread(n);
		}
	}
	
	static Comparator<thread>comstart=new Comparator<thread>() {//读者优先的comparator接口,优先时间,时间相同则先返回
		public int compare(thread o1, thread o2) {
			// TODO 自动生成的方法存根
			if(o1.starttime==o2.starttime)
			{
				return (int)(o1.type.charAt(0)-o2.type.charAt(0));// r w  先r后w
			}
			else
				return o1.starttime-o2.starttime;//返回小根堆			
		}
	};
	static Comparator<thread>comstart2=new Comparator<thread>() {//写者优先的
		public int compare(thread o1, thread o2) {
			// TODO 自动生成的方法存根
			if(o1.starttime==o2.starttime)
			{
				return (int)(o2.type.charAt(0)-o1.type.charAt(0));// w r  先w后r
			}
			else
				return o1.starttime-o2.starttime;//返回小根堆			
		}
	};
	static Comparator<thread>comend=new Comparator<thread>() {
		public int compare(thread o1, thread o2) {
			return (int)((o1.starttime+o1.totaltime)-(o2.starttime+o2.totaltime));
		}
	};
	static class thread
	{
		int id;
		String type;
		int starttime;
		int totaltime;
		public thread(int id,String type,int starttime,int totaltime)
		{
			this.id=id;
			this.type=type;
			this.starttime=starttime;
			this.totaltime=totaltime;
		}
	}

}

测试用例:

读者优先:


写者优先:

本人水平有限,?,如果有大佬发现错了,请指正。

如果对后端、爬虫、数据结构算法等感性趣欢迎关注我的个人公众号交流:bigsai

发布者:admin,转转请注明出处:http://www.yc00.com/web/1743865984a4520565.html

相关推荐

  • 戴尔电脑重装Win10的方法详解

    戴尔电脑重装Win10的方法详解 在日常使用电脑的过程中,由于系统老化、病毒感染、软件冲突等原因,我们有时需要对电脑系统进行重装。对于戴尔电脑用户而言,重装Windows 10系统并不复杂,只要按照正确的步骤操作,即可轻松完成。本文将详细

    2月前
    50
  • 用windows系统下的DOS命令将腾讯视频客户端下载的qlv文件转换成MP4格式(图文详解)

    用windows系统下的DOS命令将腾讯视频客户端下载的qlv文件转换成MP4格式&#xff08;图文详解&#xff09; 前言原理工具步骤延伸博主联系方式 前言 本人喜欢收集各种优秀的视频&#xff0c;但是很多

    1月前
    70
  • 电脑系统更新后无法上网?网络恢复步骤详解

    在进行操作系统或驱动程序更新后&#xff0c;很多用户会遇到无法连接网络的问题&#xff0c;尤其是在Windows系统中。无论是系统更新还是驱动程序更新&#xff0c;都可能导致网络连接异常。以下是一些常见的解决方

    1月前
    70
  • Windows操作系统----安全机制----对象

    对象结构 对象是对操作系统中需要保护和集中管理的资源的一种抽象&#xff0c;对象拥有统一的固定头部&#xff0c;保存着抽象出来的信息。此外还有可选头部和对象体。 nt!_OBJECT_HEADER0x000 Poin

    1月前
    50
  • 第四章:操作系统Operating System

    文章目录&#xff1a; 一&#xff1a;操作系统基础 1.基本概念 2.OS的分类 2.1 按人机界面 2.2 按用户任务 2.3 按系统时间和功能 3.Win7 Win10和Win11的区别 4.Win

    1月前
    30
  • Windows操作系统的各进程的作用

    btwdins.exe是为了微软Windows操作系统支持蓝牙技术的程序。 cisvc.exe是微软Windows操作系统自带的程序。它用于监测CIDAEMON.exe内存使用状态&#xff0c;防止可用内存过低问题,如果cidae

    1月前
    30
  • 计算机关机键 自动重启,电脑关机后自动重启怎么办?原因及解决方详解

    原标题&#xff1a;电脑关机后自动重启怎么办&#xff1f;原因及解决方详解 电脑关机后自动重启的原因是什么&#xff1f;相信有不少的用户在使用电脑的时候&#xff0c;都有遇到过电脑关机后自动重启的情况

    1月前
    70
  • 操作系统实验之银行家算法模拟

    操作系统实验之银行家算法模拟 银行家算法中的数据结构可利用资源向量 AvailableAvailable[i] 表示第 i 种资源可利用的数目最大需求矩阵 MaxMax[i][j] 表示第 i 个进程最多需要的第 j 类资源的数

    1月前
    30
  • 操作系统 实验二银行家算法

    题目描述&#xff1a; 已知进程{P0,P1,P2,P3,P4}&#xff0c;有三类系统资源A、B、C的数量分别为10、5、7&#xff0c;在T0时刻的资源分配情况如下图所示&#xff1a;&

    1月前
    30
  • 操作系统之多线程编程—读者优先写者优先详解

    操作系统之进程调度——优先权法和轮转法&#xff08;附上样例讲解&#xff09; 操作系统之银行家算法—详解流程及案例数据 操作系统之多线程编程—读者优先写者优先详解 操作系统之存储管理——FIFO算法和LRU算法 操作

    1月前
    40
  • 操作系统考试复习

    操作系统复习 选择题: 在计算机系统中,操作系统是( A )。 A、处于裸机之上的第一层软件 B、处于硬件之下的低层软件 C、处于应用软件之上的系统软件 D、处于系统软件之上的用户软件 为了使系统中所有的用户都能得到及时的响应,该操作系统

    1月前
    40
  • 操作系统学习体会之进程管理篇

    计算机基础知识的学习中&#xff0c;操作系统则是重中之重。继对微机原理和计算机组成原理的基础知识了解和学习后&#xff0c;对硬件和基础原理的理论有了初步的了解&#xff0c;结合在所在公司的项目中开发应用的经历和

    1月前
    10
  • 操作系统大全

    操作系统&#xff1a; 电脑版&#xff1a; 一、UNIX系列     Unix是20世纪70年代初出现的一个操作系统&#xff0c;除了作为网络操作系统之外&#xff0c;还可以作为单机操作系统使用

    1月前
    30
  • 李治军操作系统 笔记

    第一篇.操作系统基础 1.1 操作系统概述 1.2 操作系统引导(总体做的:将操作系统读入内存 + 初始化 ) bootsect.ssetup.s读取硬件参数读取system到内存0x00位置从16位模式 转到 32位模式,即从实时模式

    1月前
    50
  • 全网最全详解Windows CMD命令大全

    简介 cmd是command的缩写.即命令行 虽然随着计算机产业的发展&#xff0c;Windows 操作系统的应用越来越广泛&#xff0c;DOS 面临着被淘汰的命运&#xff0c;但是因为它运行安全、稳定&a

    1月前
    40
  • 一文详解基于NarrotoAI的短剧短视频自动解说、混剪AI平台搭建

    背景 前阵给孩子做电子相册学了点剪辑技术&#xff0c;就想凑个热闹剪剪短剧玩玩&#xff0c;一是学以 致用&#xff0c;再者也好奇短剧创作为啥这么火&#xff0c;跟个风。 初步了解情况后&

    1月前
    40
  • 必看:重装操作系统的20条原则

    覆盖安装不奏效&#xff0c;删除安装新一套 如果按以上所提的覆盖安装方法没有能够解决你的问题&#xff0c;那么你可以在确认备份工作完成后&#xff0c;并且各类驱动程序都已经准备好的情况下&#xff0c;

    1月前
    40
  • Win10按F8无法进入安全模式?四种实用解决方案详解

    Win10按F8无法进入安全模式?四种实用解决方案详解 作为Windows系统的核心功能之一,安全模式在故障排查、病毒清理和系统修复中发挥着不可替代的作用。然而,随着Windows 10系统的迭代更新,部分用户发现传统的F8快捷键无法直接

    1天前
    00
  • windows系统详解

    Windows 系统深度解析&#xff1a;架构、功能与演进 一、系统架构与核心组件 Windows 是由微软开发的多任务操作系统&#xff0c;采用 分层架构&#xff0c;分为 内核模式 和 用户模式&

    1天前
    20
  • 如何从官方渠道下载操作系统

    在安装或重装操作系统时&#xff0c;从官方渠道获取未经篡改的系统镜像至关重要。非官方来源可能包含恶意软件或捆绑程序&#xff0c;威胁数据安全。本文将以 Windows、macOS、Linux 为例&#xff0c;

    1天前
    00

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信