Java实现读者写者问题--读者优先
作者:凌杰林
简介
临界资源:同一时间只能由一个进程访问的资源
临界区:访问临界资源的代码段
读者写者问题:存在一个多个进程共享的数据区(临界资源),该数据区可以是一个文件或者一块内存空间,甚至可以是一组寄存器;有些进程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操作来实现,设置好互斥的相关操作,构造好该信号量的类。
Java实现读者写者问题--读者优先相关推荐
- 读者写者模型---读优先与写优先
Linux线程中写过生产者消费者模型,这次研究读者写者模型. 文章目录 读者写者模型遵循的规则 读者优先 写者优先 读者和写者公平竞争 读者写者模型遵循的规则 读者-写者模型同样遵循321规则: 写- ...
- 读者写者问题读者优先 C语言实现代码
本博客代码摘自Mic_H,我小小地修改了一些. 本博客记录自己的学习,疑问和理解.欢迎大家交流和指教. 作者原博客链接 我的代码和运行结果: #include <windows.h> #i ...
- java 读者写者_Java实现生产者消费者问题与读者写者问题详解
1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品.解决生产者/消费者问题的方法可分为两 ...
- java实现带界面的生产者消费者_Java实现生产者消费者问题与读者写者问题
1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品.解决生产者/消费者问题的方法可分为两 ...
- Java 5种方法实现生产者消费者问题与2种方法实现读者写者问题
摘要: Java实现生产者消费者问题与读者写者问题 1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从 ...
- 操作系统 读者写者问题的实现(C++ 读者优先、写者优先)
通过信号量机制和相应的系统调用,用于线程的互斥和同步,实现读者写者问题.利用信号量机制,实现读者写者问题. 在windows 10环境下,创建一个控制台进程,此进程包含n个线程.用这n个线程来表示n个 ...
- 读者写者问题(读者优先)
一.读者写者问题定义 存在一个多个进程共享的数据区,该数据区可以是一个文件或一块内存空间,甚至可以是一组寄存器:有些进程(reader)只读取这个数据区中的数据,有些进程(writer)只往数据区中写 ...
- Linux多线程实践(6) --Posix读写锁解决读者写者问题
Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restr ...
- 读者写者问题(超详细讲解)看不懂算我输
文章目录 读者写者问题 读者优先 1.初始化 2.写者 3.读者 写者优先 1.初始化 2.读者 3.写者 4.考虑读者1->写者1->读者2的情况 读者写者问题 1.允许多个读者可以同时 ...
最新文章
- aspx-cs-dll :在部署后就让所有的aspx处于已经编译成dll的状态
- mysql 并发避免锁表_MYSQL锁表的用法,防止并发情况下的重复数据
- Intel Realsense D435 如何获取摄像头的内参?get_profile() video_stream_profile() get_intrinsics()
- linux java 生成证书_Java 制作证书(Windows 和Linux)
- Jmeter测试并发https请求成功了
- CentOS7下使用yum安装MariaDB
- 深度学习的实用层面 —— 1.14 关于梯度检验实现的标记
- css里面的位置属性,CSS定位属性Position详解
- 又是AI+IoT!谷歌试图收购物联网公司Xively
- 戴尔携手EMC战略合作续签至2013年
- centos7查看设置IP地址
- idea启动崩溃问题
- 台式计算机设备验收单,电脑设备验收单.doc
- Python办公自动化——8行代码实现文件去重
- android 扫描动画效果图,RadarView之自定义雷达扫描动画效果。
- 【寒江雪】Go实现工厂模式
- html图形渐变颜色一半一半,CSS3第八课:重复线性渐变repeating-linear-gradient
- 【Hibernate步步为营】--最后的集合映射
- axios 的响应结构
- lisp不是函授型语言_讨论:为什么Lisp语言不再被广泛使用