Java实现读者写者问题--读者优先

article/2025/9/30 8:17:37

作者:凌杰林

简介

临界资源:同一时间只能由一个进程访问的资源

临界区:访问临界资源的代码段

读者写者问题:存在一个多个进程共享的数据区(临界资源),该数据区可以是一个文件或者一块内存空间,甚至可以是一组寄存器;有些进程reader只读取这个数据区的数据,有些进程writer只往数据区中写数据。此外,还需要满足以下条件:

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

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

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

4.读者优先:必须等所有读进程读完才可以写。

也即是说,读进程不排斥其它读进程,而写进程排斥其它所有进程,包括读进程和写进程。

分析

在这里插入图片描述

类的编写

Semaphore类

利用Java的多线程编程实现,操作系统中的p,v操作。p,v操作的函数添加synchronized关键字,加锁,确保同一时刻只有一个进程可以操作semValue这个临界资源,否则多个进程同时访问该值,会出现错误。

public class Semaphore{private int semValue;//定义信号量public Semaphore(int semValue) {this.semValue = semValue;}public synchronized void p() {semValue--;if (semValue < 0) {try {this.wait();//阻塞该进程} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void v(){semValue++;if (semValue <= 0) {this.notify();//唤醒被阻塞的进程}}
}

Reader类

定义读者类,实现Runnable接口,重写run方法。

class Reader implements Runnable{private Semaphore rmutex,wmutex;My my;static int readcount = 0;public Reader(Semaphore rmutex,Semaphore wmutex,My my){this.rmutex = rmutex;this.wmutex = wmutex;this.my = my;}@Overridepublic void run() {try{Thread.sleep((int)(1000*my.arrive_time));}catch (InterruptedException e){e.printStackTrace();}System.out.println("线程" + my.thread + "申请读操作");rmutex.p();if (readcount == 0) wmutex.p();readcount++;rmutex.v();System.out.println("线程" + my.thread + "开始读操作");try{Thread.sleep((int)(1000*my.operate_time));} catch (InterruptedException e){e.printStackTrace();}rmutex.p();readcount--;System.out.println("线程" + my.thread + "结束读操作");if (readcount == 0) wmutex.v();rmutex.v();}
}

细节

实现读者优先,定义readcount变量,初始值为0,用于记录当前读者进程的数量,第一个读者负责上锁,防止写进程申请资源,最有一个读进程负责解锁,唤醒被阻塞的写进程

Writer类

定义写者类,实现Runnable接口,重写run方法。

class Writer implements Runnable{private Semaphore wmutex;My my;public Writer(Semaphore wmutex,My my){this.wmutex = wmutex;this.my = my;}@Overridepublic void run() {try{Thread.sleep((int)(1000*my.arrive_time));}catch (InterruptedException e){e.printStackTrace();}System.out.println("线程" + my.thread + "申请写操作");wmutex.p();System.out.println("线程" + my.thread + "开始写操作");try{Thread.sleep((int)(1000*my.operate_time));}catch (InterruptedException e){e.printStackTrace();}wmutex.v();System.out.println("线程" + my.thread + "完成写操作");}
}

其他类

该类定义了一个进程的编号,到达时间,读/写类型,要求服务时间。

class My
{int thread;String type;double arrive_time;double operate_time;My(String s){StringTokenizer st=new StringTokenizer(s);thread = Integer.parseInt(st.nextToken());type = st.nextToken();arrive_time = Double.parseDouble(st.nextToken());operate_time = Double.parseDouble(st.nextToken());}

该类是主类

import java.io.*;
import java.util.*;
public class ReaderWriter
{public static void main(String[] args) {Semaphore wmutex = new Semaphore(1);Semaphore rmutex = new Semaphore(1);int i;String s=null;My m[]=new My[10];try{BufferedReader br=new BufferedReader(new FileReader("Input.txt"));for (i=0;(s=br.readLine())!=null;i++) {m[i]=new My(s);System.out.println("线程"+m[i].thread+"是"+m[i].type+"线程,第"+m[i].arrive_time+"秒申请读写操作,操作持续"+m[i].operate_time+"秒");if (m[i].type.equals("R")){new Thread(new Reader(rmutex,wmutex,m[i])).start();}else {new Thread(new Writer(wmutex,m[i])).start();}}}catch(IOException e){}	}
}

数据格式

1 R 1 5

2 W 3 4

数据存储在同目录下的input.txt文件中。

源代码

public class Semaphore{private int semValue;public Semaphore(int semValue) {this.semValue = semValue;}public synchronized void p() {semValue--;if (semValue < 0) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void v(){semValue++;if (semValue <= 0) {this.notify();}}
}//另外一个类
import java.io.*;
import java.util.*;
public class ReaderWriter
{public static void main(String[] args) {Semaphore wmutex = new Semaphore(1);Semaphore rmutex = new Semaphore(1);int i;String s=null;My m[]=new My[10];try{BufferedReader br=new BufferedReader(new FileReader("Input.txt"));for (i=0;(s=br.readLine())!=null;i++) {m[i]=new My(s);System.out.println("线程"+m[i].thread+"是"+m[i].type+"线程,第"+m[i].arrive_time+"秒申请读写操作,操作持续"+m[i].operate_time+"秒");if (m[i].type.equals("R")){new Thread(new Reader(rmutex,wmutex,m[i])).start();}else {new Thread(new Writer(wmutex,m[i])).start();}}}catch(IOException e){}	}
}
class Reader implements Runnable{private Semaphore rmutex,wmutex;My my;static int readcount = 0;public Reader(Semaphore rmutex,Semaphore wmutex,My my){this.rmutex = rmutex;this.wmutex = wmutex;this.my = my;}@Overridepublic void run() {try{Thread.sleep((int)(1000*my.arrive_time));}catch (InterruptedException e){e.printStackTrace();}System.out.println("线程" + my.thread + "申请读操作");rmutex.p();if (readcount == 0) wmutex.p();readcount++;rmutex.v();System.out.println("线程" + my.thread + "开始读操作");try{Thread.sleep((int)(1000*my.operate_time));} catch (InterruptedException e){e.printStackTrace();}rmutex.p();readcount--;System.out.println("线程" + my.thread + "结束读操作");if (readcount == 0) wmutex.v();rmutex.v();}
}
class Writer implements Runnable{private Semaphore wmutex;My my;public Writer(Semaphore wmutex,My my){this.wmutex = wmutex;this.my = my;}@Overridepublic void run() {try{Thread.sleep((int)(1000*my.arrive_time));}catch (InterruptedException e){e.printStackTrace();}System.out.println("线程" + my.thread + "申请写操作");wmutex.p();System.out.println("线程" + my.thread + "开始写操作");try{Thread.sleep((int)(1000*my.operate_time));}catch (InterruptedException e){e.printStackTrace();}wmutex.v();System.out.println("线程" + my.thread + "完成写操作");}
}
class My
{int thread;String type;double arrive_time;double operate_time;My(String s){StringTokenizer st=new StringTokenizer(s);thread = Integer.parseInt(st.nextToken());type = st.nextToken();arrive_time = Double.parseDouble(st.nextToken());operate_time = Double.parseDouble(st.nextToken());}}

小结

读者-写者问题为我们解决互斥问题提供了一种参考思路,核心的思想时,在于设置一个计数器readcount记录当前正在访问共享文件的进程数目,用readcount的值来判断是否为最后一个或者最先一个读者进程,从而实现加锁或者解锁。另外,对readcount的检查和赋值操作要一气呵成,就是“原子性”,这时候,我们就应该想到要用操作系统课中的P,V操作来实现,设置好互斥的相关操作,构造好该信号量的类。


http://chatgpt.dhexx.cn/article/rW2TVRSa.shtml

相关文章

操作系统实验:读者写者问题

一&#xff0e;实验目的&#xff1a; 通过实现读者写者问题理解进程及信号量的概念 二&#xff0e;实验要求&#xff1a; 创建一个控制台进程&#xff0c;此进程包含n个线程。用这n个线程来表示n个读者或写者。每个线程按相应测试数据文件的要求进行读写操作。用信号量机制分…

信号量机制——读者-写者问题

信号量机制——读者-写者问题 问题描述 一个共享数据区&#xff0c;有若干个进程负责对其进行读入工作&#xff0c;若干个进程负责对其进行写入工作。 允许多个进程同时读数据互斥读数据若有进程写数据&#xff0c;不允许读者读数据 对照生活中的购票系统&#xff1a; 一个…

操作系统:读者写者问题

操作系统&#xff1a;读者写者问题 问题&#xff1a;一、读者-写者问题: 读者优先二、读者-写者问题&#xff1a;写进程优先 三、读者写者问题的应用---独木桥问题类型1.一次只能过一辆车类型2.一次能过多辆车 四、总结附代码&#xff1a;//读者优先//写者优先//公平竞争 教材原…

四、操作系统——读者写者问题(详解)

一、问题描述&#xff1a; 二、需要满足的条件&#xff1a; 写进程与写进程之间必须互斥的写入数据&#xff08;因为如果两个写进程同时对共享数据中的区域A中的数据进行写操作的话&#xff0c;会导致数据错误覆盖的问题&#xff09;写进程与读进程之间必须互斥的访问共享数据…

锁机制:读者写者问题 Linux C

最近碰到一些锁机制的问题&#xff0c;想起大三的时候做过的一个小课设&#xff0c;记录复习一下。 问题描述&#xff1a; 一个数据文件可以被多个进程共享&#xff0c;其中&#xff0c;有些进程要求读&#xff08;reader进程&#xff09;&#xff0c;而另一些进程要求对数据…

写优先的读者写者问题(Java实现)

该题系吉林大学19级软件学院操作系统课设题之一 先输入初始时的写者读者情况&#xff0c;优先级顺序做了随机处理 代码如下 GUI&#xff1a; import javax.swing.*; import javax.swing.border.Border; import javax.swing.text.BadLocationException; import javax.swing.tex…

操作系统读者写者问题代码实现

问题分析&#xff1a; 读者优先: 读者进程执行: 无其他读者写者, 直接执行有写者等, 但其他读者在读, 直接读有写者写, 等待写者进程执行: 无其他读写者, 直接执行有其他读写者, 等待 写者优先: 读者进程执行: 如果此时没有写者等待, 直接执行如果有写者等待, 那么等待写者…

读者写者问题详解 操作系统

2.16 读者写者问题 抽象解释 多个进程访问一个共享的数据区读者&#xff08;读进程&#xff09;只能读数据&#xff0c;写者&#xff08;写进程&#xff09;只能写数据适用于数据库、文件、内存、寄存器等数据区的访问模型如12306购票系统&#xff0c;由于用户量庞大和数据量…

同步机制—读者写者问题

【实验目的】 理解临界区和进程互斥的概念&#xff0c;掌握用信号量和PV操作实现进程互斥的方法。 【实验内容】 在windows或者linux环境下编写一个控制台应用程序&#xff0c;该程序运行时能创建N个线程&#xff0c;其中既有读者线程又有写者线程&#xff0c;它们按照事先设计…

操作系统——读者写者问题

一、问题描述 要求: 1、允许多个读者可以同时对文件执行读操作。 2、只允许一个写者往文件中写信息。 3、任一写者在完成写操作之前不允许其他读者或写者工作。 4、写者执行写操作前,应让已有的读者和写者全部退出。 二、问题分析 读者写者问题最核心的问题是如何处理…

【操作系统-进程】PV操作——读者写者问题

文章目录 读者写者问题万能模板万能模板 1——读进程优先万能模板 2——读写公平法万能模板 3——写进程优先 题目 1&#xff1a;南北过桥问题题目 2&#xff1a;录像厅问题题目 3&#xff1a;更衣问题 读者写者问题万能模板 读者写者问题&#xff0c;其本质就是连续多个同类进…

经典进程同步问题(三)——读者写者问题

目录 一、问题描述 二、解题思路 2.1 读者优先算法 2.2 写者优先算法 2.3 读写公平 三、源码实现 3.1 读者优先 3.2 写者优先 3.3 读写平等 一、问题描述 一个数据问价或记录可以被多个进程共享&#xff0c;我们把只读该文件的进程称为“读者进程”&#xff0c;其他进…

2. 堆与栈的区别

2. 堆与栈的区别 在理解这两个概念时&#xff0c;需要放到具体的场景下&#xff0c;因为不同场景下&#xff0c;堆与栈代表不同的含义。一般情况下&#xff0c;有两层含义&#xff1a; &#xff08;1&#xff09;程序内存布局场景下&#xff0c;堆与栈表示的是两种内存管理方式…

栈与堆的区别(内存分配与数据结构)

参考自https://blog.csdn.net/K346K346/article/details/80849966/ 堆&#xff08;Heap&#xff09;与栈&#xff08;Stack&#xff09;包含两层含义&#xff1a; 程序内存布局场景下的内存管理方式数据结构中的两种常见的数据结构 1. 程序内存分配中的堆与栈 1.1 栈介绍 …

C语言里栈和堆的区别整理

这里说的是C语言程序内存分配中的堆和栈。下面先谈谈C语言的内存管理&#xff1a; 可执行程序在存储时&#xff08;没有调到内存&#xff09;分为代码区&#xff08;text&#xff09;、数据区&#xff08;data&#xff09;和未初始化数据区&#xff08;bss&#xff09;3个部分。…

看懂堆与栈的区别与联系

<div class"simditor-body clearfix" style"height: auto; overflow: inherit;"><h2> <strong>  堆和栈概要</strong></h2>在计算机领域&#xff0c;堆栈是一个不容忽视的概念&#xff0c;堆栈是两种数据结构。堆栈都是一…

C语言:栈和堆的区别

c语言五大内存分区 栈区&#xff08;stack&#xff09;:存放函数形参和局部变量&#xff08;auto类型&#xff09;&#xff0c;由编译器自动分配和释放 堆区&#xff08;heap&#xff09;:该区由程序员申请后使用&#xff0c;需要手动释放否则会造成内存泄漏。如果程序员没有手…

什么是栈(Stack)?什么是堆(Heap)?栈和堆的区别是什么?

原参考地址&#xff1a;https://zhidao.baidu.com/question/36918441.html 栈&#xff1a;由操作系统自动分配释放 &#xff0c;存放函数的参数值&#xff0c;局部变量du的值等。其操作方式类似于数据结构中的栈&#xff1b; 堆&#xff1a; 一般由程序员分配释放&#xff0c…

堆和栈的概念和区别

在说堆和栈之前&#xff0c;我们先说一下JVM&#xff08;虚拟机&#xff09;内存的划分&#xff1a; Java程序在运行时都要开辟空间&#xff0c;任何软件在运行时都要在内存中开辟空间&#xff0c;Java虚拟机运行时也是要开辟空间的。JVM运行时在内存中开辟一片内存区域&#x…

堆与栈的区别详细总结

1、堆与栈的区别详细总结_Fighting的博客-CSDN博客_堆和栈的区别 2、堆和栈的区别 - 江雨牧 - 博客园 3、堆和栈的区别_内外皆秀的博客-CSDN博客_堆和栈的区别 4、一文读懂堆与栈的区别_恋喵大鲤鱼的博客-CSDN博客_堆和栈的区别 一般情况下&#xff0c;如果有人把堆栈合起来…