进程同步问题是一个非常重要且相当有趣的问题,本篇我们对其中比较有名的读者-写者问题来进行学习。

读者-写者

问题描述

假设一个数据库为多个并发进程所共享。有的进程可能只需要读数据库,而另一些进程可能更新(即)数据库。为了区分这两种类型的进程,我们称前者为读者(Reader),称后者为写者(Writer)。显然,如果多个读者同时访问共享数据,而不会产生副作用。但如果某个写者和其他进程(或读者或写者)同时访问数据库时可能导致数据不一致的错误。

为了确保不会出现数据不一致的问题,要求写者在写入数据库时具有共享数据库独占的访问权限。这一同步问题称为读者-写者问题(reader-writer problem)。

所以读者-写者问题要求:

  1. 允许多个读者同时执行读操作;
  2. 不允许多个写者同时操作;
  3. 不允许读者、写者同时操作。

解决策略

读者-写者问题要解决: 读、读共享;写、写互斥;写、读互斥。

写者是比较简单的,它与任何线程互斥,用互斥信号量P操作、V 操作即可解决。

读者的问题比较复杂,它必须实现与写者的互斥,多个读者还可以同时读。仅仅简单的一对P操作、V操作是无法解决的。

可以有三种策略:读者优先写者优先读写公平

读者优先

读进程只要看到有其他读进程正在访问文件,就可以继续作读访问;写进程必须等待所有读进程都不访问时才能写文件,即使写进程可能比一些读进程更早提出申请。可以使用一个计数器read_count记录读者总数目(包含等待和正在读的数目),如果read_count > 0 则写者等待,而读者直接读。当read_count = 0 写者与写者、写者与第一个读者抢占读写操作,这可以用一个二元信号量rw_mutex进行互斥访问。因为多个读者线程都要访问计数器,则使用一个二元信号量mutex进行互斥访问。

需要用到的共享变量:

int read_count = 0; // 系统当前读者进程数量semaphore rw_mutex = 1; // 读者与写者互斥访问共享数据的互斥信号量 semaphore mutex = 1;    // 多个读者进程互斥修改当前读者进程数量的信号量

写者进程结构

do {P(rw_mutex);.../* 修改共享数据 */...V(rw_mutex);}while(true);

读者进程结构

do {P(mutex); //获取修改读者进程数量的互斥信号量,该操作在请求rw_mutex之前,防止出现死锁read_count++;if(read_count == 1)  //判断当前是否为第一个读者进程 P(rw_mutex);  //如果是就需要请求访问共享数据的互斥信号量V(mutex);  //read_count修改后 释放信号量.../* 读取数据 */...P(mutex);  //获取修改读者进程数量的互斥信号量read_count--;if(read_count == 0)  //判断当前进程是否为最后一个读者进程 V(rw_mutex);  //如果是则释放共享数据的互斥信号量,以允许写者进程操作共享数据V(mutex);}while(true);

读者优先有可能导致写者进程产生饥饿现象,当系统中不断出现读者进程时,写者进程始终无法进入临界区。

写者优先

需要用到的共享变量:

int read_count = 0;         // 系统当前读者进程数量int write_count = 0;        // 系统当前写者进程数量semaphore rw_mutex = 1;     // 读者与写者互斥访问共享数据的互斥信号量semaphore r_mutex = 1;      // 互斥修改当前读取文件的进程数semaphore w_mutex = 1;      // 互斥修改当前修改文件的进程数semaphore enter_mutex = 1;  // 获取申请访问文件的权限

写者进程结构

do {    P(w_mutex);  //P操作 新的写者进程进入,上锁进行写者计数更新    write_count++;   //更新写者计数器  if(write_count == 1)  // 判断当前是否为第一个写者进程        P(enter_mutex); //P操作 则抢enter_mutex的锁,阻断后续到达的读者进程  V(w_mutex);         //V操作        P(rw_mutex);  //获取访问文件的权限,文件可能被其它写者进程占用,或者等待最后一个读者进程释放    ...  /* 修改数据 */    ...  V(rw_mutex);    P(w_mutex);  write_count--;  if(write_count == 0)  // 当所有写者进程都放弃使用文件时,运行读者进程申请访问文件  V(enter_mutex);  V(w_mutex);}while(true);

读者进程结构

do {    P(enter_mutex);  // 获取申请访问文件的权限     P(r_mutex);      //上锁进行读者计数更新    read_count++;       //更新读者计数器  if(read_count == 1)  // 判断当前是否为第一个读者进程        P(rw_mutex);  // 占用文件  V(r_mutex);    V(enter_mutex); //    ...   /* 读取数据 */    ...    P(r_mutex);  read_count--;  if(read_count == 0)   P(rw_mutex);   // 释放文件  P(r_mutex);}while(true);

写者优先有可能导致读者进程产生饥饿现象,当系统中不断出现写者进程时,读者进程始终无法进入临界区。

读写公平

需要用到的共享变量:

int read_count = 0;         // 系统当前读者进程数量semaphore rw_mutex = 1;     // 读者与写者互斥访问共享数据的互斥信号量semaphore r_mutex = 1;      // 互斥修改当前读取文件的进程数semaphore enter_mutex = 1;  // 获取申请访问文件的权限

写者进程结构

do {     P(enter_mutex); // 阻断后续到达的读者进程     P(rw_mutex);      ...     /* 修改数据 */      ...     V(rw_mutex);     V(enter_mutex); }while(true);

读者进程结构

do {    P(enter_mutex);  // 获取申请访问的权限,这里与写者优先的区别在于,写者放弃占用文件时,所有读者                            都可以与写者进程进行再次竞争     P(r_mutex);    read_count++;  if(read_count == 1)  // 判断当前是否为第一个读者进程        P(rw_mutex);  signal(r_mutex);    signal(enter_mutex);  // 释放许可,其余读者和写者进程将进行下一轮竞争   ...   /* 读取数据 */   ...    wait(r_mutex);  read_count--;  if(read_count == 0)   signal(rw_mutex);  signal(r_mutex);}while(true);

上面的代码的 读者进程结构其实和第二个写者优先的 读者进程结构 是一样的,不一样的是写者进程结构。写者进程变成在每次写操作前都要等待 enter_mutex信号量。这里的P(enter_mutex) P操作并不会出现写者优先,而是按照先进先出的顺序让读者写者使用资源。

读者写者问题 设置有限的读者_操作系统基础16-读者写者问题相关推荐

  1. 新时期修谱,谱序要怎么写?最新修谱攻略让你零基础也能写出谱序

    序,是一本书中不可或缺的部分.序记载了作者的想要向读者表达的写书意图.宗旨等.汉代孔安国曾说:"序者,所以叙作者之意也."家谱也有序言,一般家族的谱序有自序和他序两种:自序就是编纂 ...

  2. 业务逻辑写在存储过程好还是后端好_用存储过程和 JAVA 写报表数据源有什么差异...

    我们在报表开发中经常会使用存储过程准备数据,存储过程支持分步计算,可以实现非常复杂的计算逻辑,为报表开发带来便利.所以,报表开发中这样的存储过程并不少见: 3008 行,141KB 的存储过程,会给报 ...

  3. 写java接口的文档工具_【java】适合写接口文档的工具,或者文本语法

    由于后端与前端使用ajax交互,后端写接口文档变得非常有必要.以前我习惯用word写接口文档,但是最近与同事合作编写后端,word并不适合使用svn工具做同步,因为svn.git等无法自动合并word ...

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

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

  5. 如何写一个脚本语言_零基础小白如何学会写文案?文案写作技巧之一:如何写一个吸引读者的文案开头...

    我文笔不好怎样才能够写出优质的文案?很多人都有这个疑问,包括我自己在学习新媒体运营之前,这也是我最大的困惑.现在是内容为王的时代,你的文章质量决定了你的KPI. 后来我学习了文章的写作结构和技巧后,就 ...

  6. 操作系统课程设计----读者-写者 问题(c语言)

    问题描述: 所谓读者写着问题,是指保证一个writer进程必须与其他进程互斥地访问共享对象的同步问题.读者写者问题可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以 ...

  7. 【Python】写文件个性化设置模块Python_Xlwt练习

    python:写文件个性化设置模块Python_Xlwt练习 # -*- coding: utf-8 -*- """ Created on Sun Aug 5 22:52 ...

  8. 【.net 深呼吸】自己动手来写应用程序设置类

    在开始装逼之前,老周先说明一件事.有人说老周写的东西太简单了,能不能写点复杂点.这问题就来了,要写什么东西才叫"复杂"?最重要的是,写得太复杂了,一方面很多朋友看不懂,另一方面,连 ...

  9. 涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况。每位读者有一个编号,每条记录用读者的编号来表示。给出读者的来访记录,请问每一条记录中的读者是第几次出现?

    题目:涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况.每位读者有一个编号,每条记录用读者的编号来表示.给出读者的来访记录,请问每一条记录中的读者是第几次出现. 输入描述: 输入的第一行包 ...

  10. 在钉钉上怎么手写_数码知识:钉钉手写签名如何设置开启手写签名教程

    如今使用IT数码设备的小伙伴们是越来越多了,那么IT数码设备当中是有很多小技巧的,这些技巧很多小伙伴一般都是不知道如何来实用的,就好比最近就有很多小伙伴们想要知道钉钉手写签名如何设置开启手写签名教程, ...

最新文章

  1. 一个查看全部用户的磁盘空间使用情况的脚本
  2. 深入理解 RPC : 基于 Python 自建分布式高并发 RPC 服务
  3. 延长线段ab到c的画法有几种_终于有人把趋势线的正确画法和错误画法讲透彻了,字字精华,原来大多数人都画错了...
  4. Vcastr 3.0 - flash video(flv) player (开源 Open Source)
  5. matlab龙格库塔法求通解,基于matlab及龙格库塔法求解布拉修斯方程.doc
  6. 容器的访问元素的成员函数(front,back,下标和at)返回的都是引用
  7. 1003 Emergency (25 分)【Dijastra与DFS解法】
  8. pythonjieba分词_$好玩的分词——python jieba分词模块的基本用法
  9. 开源 区块链_区块链如何补充开源
  10. 今日头条10.82亿元拿下 “中国最牛街道”土地:将与腾讯、阿里做邻居
  11. 安卓(android)建立项目时失败,出现Android Manifest.xml file missing几种解决方法?(总结中)
  12. 简述linux开机启动进程,Linux系统启动流程简述
  13. 图片上传至服务器实现压缩
  14. 【Animations】使用弹簧物理学动画运动(8)
  15. Atitit 前端重要概念和趋势总结 大前端 目录 1. 大前端 1 2. 三个层面上的大前端 1 2.1. 大前端与NodeJS与前后端分离 1 2.2. 微信Web 1 2.3. React
  16. python写一个定时关机软件
  17. 不加好友实现QQ在线代码状态临时会话
  18. 联想台式计算机设置u盘启动不了,联想台式电脑bios设置u盘启动教程
  19. JUC并发编程学习笔记
  20. 震惊!黄光裕、李嘉诚、马化腾甚至股市中的“野蛮人”都出自潮汕帮(附股)

热门文章

  1. 同大取大同小取小口诀图解_七年级下册数学课本内容归纳汇总
  2. python迭代器和生成器_python迭代器和生成器
  3. hive循环语句_Hive 如何方便地实现存储过程?
  4. php 数组 utf8,PHP数组编码gbk与utf8互相转换的两种方法实例分享
  5. 手机打开电脑端网页_网站建设要把电脑端手机端都做好
  6. mysql取分组最新的一条_基于mysql实现group by取各分组最新一条数据
  7. JAVA 线程池的分析和使用
  8. (13)Spring框架----Spring与Mybatis的框架整合(XML配置详解)
  9. (1)Spring框架----通俗易懂的IoC原理
  10. position四个属性值的关系