作者:凌杰林

简介

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

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

读者写者问题:存在一个多个进程共享的数据区(临界资源),该数据区可以是一个文件或者一块内存空间,甚至可以是一组寄存器;有些进程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实现读者写者问题--读者优先相关推荐

  1. 读者写者模型---读优先与写优先

    Linux线程中写过生产者消费者模型,这次研究读者写者模型. 文章目录 读者写者模型遵循的规则 读者优先 写者优先 读者和写者公平竞争 读者写者模型遵循的规则 读者-写者模型同样遵循321规则: 写- ...

  2. 读者写者问题读者优先 C语言实现代码

    本博客代码摘自Mic_H,我小小地修改了一些. 本博客记录自己的学习,疑问和理解.欢迎大家交流和指教. 作者原博客链接 我的代码和运行结果: #include <windows.h> #i ...

  3. java 读者写者_Java实现生产者消费者问题与读者写者问题详解

    1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品.解决生产者/消费者问题的方法可分为两 ...

  4. java实现带界面的生产者消费者_Java实现生产者消费者问题与读者写者问题

    1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品.解决生产者/消费者问题的方法可分为两 ...

  5. Java 5种方法实现生产者消费者问题与2种方法实现读者写者问题

    摘要: Java实现生产者消费者问题与读者写者问题 1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从 ...

  6. 操作系统 读者写者问题的实现(C++ 读者优先、写者优先)

    通过信号量机制和相应的系统调用,用于线程的互斥和同步,实现读者写者问题.利用信号量机制,实现读者写者问题. 在windows 10环境下,创建一个控制台进程,此进程包含n个线程.用这n个线程来表示n个 ...

  7. 读者写者问题(读者优先)

    一.读者写者问题定义 存在一个多个进程共享的数据区,该数据区可以是一个文件或一块内存空间,甚至可以是一组寄存器:有些进程(reader)只读取这个数据区中的数据,有些进程(writer)只往数据区中写 ...

  8. Linux多线程实践(6) --Posix读写锁解决读者写者问题

    Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restr ...

  9. 读者写者问题(超详细讲解)看不懂算我输

    文章目录 读者写者问题 读者优先 1.初始化 2.写者 3.读者 写者优先 1.初始化 2.读者 3.写者 4.考虑读者1->写者1->读者2的情况 读者写者问题 1.允许多个读者可以同时 ...

最新文章

  1. aspx-cs-dll :在部署后就让所有的aspx处于已经编译成dll的状态
  2. mysql 并发避免锁表_MYSQL锁表的用法,防止并发情况下的重复数据
  3. Intel Realsense D435 如何获取摄像头的内参?get_profile() video_stream_profile() get_intrinsics()
  4. linux java 生成证书_Java 制作证书(Windows 和Linux)
  5. Jmeter测试并发https请求成功了
  6. CentOS7下使用yum安装MariaDB
  7. 深度学习的实用层面 —— 1.14 关于梯度检验实现的标记
  8. css里面的位置属性,CSS定位属性Position详解
  9. 又是AI+IoT!谷歌试图收购物联网公司Xively
  10. 戴尔携手EMC战略合作续签至2013年
  11. centos7查看设置IP地址
  12. idea启动崩溃问题
  13. 台式计算机设备验收单,电脑设备验收单.doc
  14. Python办公自动化——8行代码实现文件去重
  15. android 扫描动画效果图,RadarView之自定义雷达扫描动画效果。
  16. 【寒江雪】Go实现工厂模式
  17. html图形渐变颜色一半一半,CSS3第八课:重复线性渐变repeating-linear-gradient
  18. 【Hibernate步步为营】--最后的集合映射
  19. axios 的响应结构
  20. lisp不是函授型语言_讨论:为什么Lisp语言不再被广泛使用

热门文章

  1. 向量的内积(点乘)与外积(叉乘)
  2. MobaXterm 终端界面 修改背景颜色
  3. ASP.NET Core 中的 wwwroot 文件夹
  4. 为什么要查“圣诞树”
  5. log in stackflow
  6. Windows Phone Pivot 模拟 滑动Image Viewer 出现 0x8000ffff 异常
  7. 解决CC2530在zstack中无法进入P0中断的问题
  8. JoVE软体机器人组专刊征稿,拍视频即可发SCI
  9. 搭建轻量级的容器管理平台-Humpback
  10. K210与STM32通信(串口通信)