问题背景:多个线程对一个共享的资源进行读写访问。写线程之间需要互斥,读线程跟写线程需要互斥,读线程之间不用互斥。

早些时候听张sir的课,讲述java5中增强并发的功能。用java.util.concurrent.locks中ReadWriteLock 可以轻松解决读写锁问题。我在思考如果没有ReadWriteLock,单靠synchronized可以怎样做呢? 的确,比较麻烦。

1.结合张sir传授的面向对象的设计思想,首先设计一个业务类Business作为共享资源,封装write跟read方法。

2.因为write必定互斥,所以直接定义synchronized。

3.read之间不要互斥 所以read 不能直接定义synchronized的 但是 write跟read 需要互斥 如何控制 我想到的一个方法是在read里 加入synchronized(this){} 同时定义readThreads计数器作为信号量 我试想下会出现下面几种情况:

read[m]表示某个线程的read方法 。

write[n] 同上

1>read[m]中执行到synchronized(this){readThreads++;}时 write[n]来了 write[n] 会被自身的synchronized阻塞。

2>read[m]在do something(此时无锁)时 write[n] 来了 因为 readThreads!=0 而被迫wait。

3> 每次read[m]结束时 wait中的write[n]会被notify 但如果发现还有其他的read的话 write[n] 只能无奈地再次wait。

4>当readThreads==0并且调用notifyAll 时 read[m] 和 write[n] 会竞争cpu 如果write[n]再次落败,则会出现1>或3> ; 如果成了,则如下:

5> 如果write[n] wait中醒来占锁,read[m]被阻塞synchronized(this){readThreads++;}之上。

6>如果被阻塞的write[n]占锁,read[m]被阻塞synchronized(this){readThreads++;}之上。

从以上看来read 和 write 是互斥的。

4.实现细节如下:

packagecommunication;

importjava.util.Random;

publicclassReadWriteLockTest {

publicstaticvoidmain(String[] args){

finalBusiness business =newBusiness();

//启动4线程 2读 2写

for(inti=1;i<=2;i++){

newThread(newRunnable(){

publicvoidrun() {

for(intj=1;j<1000;j++){

business.read();

try{

Thread.sleep(900);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

newThread(newRunnable(){

publicvoidrun() {

Random r =newRandom();

for(intj=1;j<1000;j++){

inti = r.nextInt(100);

business.write(i);

try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

}

}

}

//封装的业务类

classBusiness{

privateintdata=0;//共享资源属性

privateintreadThreads =0;//读线程数

//private boolean isWriting  = false;

//是否执行写 后来发现不需要 当write抢占锁时 所有的read 都被挡在synchronized (this){}之上 无机会执行wait

publicvoidread(){

synchronized(this) {

/*while(isWriting){

try {

this.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}*/

//readThreads不被锁的话 会出现read和write不互斥的小概率事件 导致线程不安全

readThreads++;

}

System.out.println(Thread.currentThread().getName()+" read begin");

System.out.println(Thread.currentThread().getName()+" read:"+data);

System.out.println(Thread.currentThread().getName()+" read finish");

synchronized(this) {

readThreads--;

this.notifyAll();

}

}

publicsynchronizedvoidwrite(inti){

while(readThreads !=0){//当read 正处于do something状态时 来个write 那就只有等等先了

try{

this.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

//isWriting = true;

System.out.println(Thread.currentThread().getName()+" write start");

data = i;

System.out.println(Thread.currentThread().getName()+" write:"+i);

System.out.println(Thread.currentThread().getName()+" write over");

//isWriting = false;

this.notifyAll();

}

}

思考中:

5.当读频繁时 readThreads会长时间!= 0 写线程会饿死 这个可以如何解决?

java自己实现读写锁_关于读写锁算法的Java实现及思考相关推荐

  1. java 实现队列读写锁_史上最全的Java并发系列之Java中的锁的使用和实现介绍(二)...

    前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger 种一棵树最好的时间是十年前,其次是现在 絮叨 上节是锁的第一 ...

  2. java内存中读文件_关于内存管理:读取Java中的大文件

    我需要一个非常了解Java和内存问题的人的建议. 我有一个大文件(大约1.5GB),我需要将此文件切成许多小文件(例如100个小文件). 我通常知道如何做到这一点(使用BufferedReader), ...

  3. java 多线程 并发 面试题_最常见的15个Java多线程,并发面试问题

    假设你有三个线程T1,T2,T3.你如何能保证线程T2在线程T1后运行,T3在T2后运行 这个线程面试问题大多是在第一轮或电话筛选轮次中会被问到的,这个多线程问题的目的是检查候选人对"joi ...

  4. 用Java代码实现日志记录器_如何在此简单的Java日志记录实现中附加到日志文件? - java...

    我得到了以下用于创建和管理Logger的类.每当执行代码和程序时,都会使用对静态getLogger()捕获块的调用进行记录. public class Log { private static fin ...

  5. java能调用python吗_如何使用运行时在Java中调用python程序 - java

    我想用来自Java的参数调用python程序.但是我的输出是空白.代码在这里. Python代码在这里: import sys print(sys.argv[1]) Java代码在这里: public ...

  6. java虚拟机内存模型种类_深入理解volatile类型——从Java虚拟机内存模型角度

    一.前言 在java多线程编程中,volatile可以用来定义轻量级的共享变量,它比synchronized的使用成本更低,因为它不会引起线程上下文的切换和调度.所谓知己知彼.百战不殆.本文从JVM内 ...

  7. java实现 k nn算法_数据挖掘(二)——Knn算法的java实现

    本文接数据挖掘-基于Kmeans算法.MBSAS算法及DBSCAN算法的newsgroup18828文本聚类器的JAVA实现(上). (update 2012.12.28 关于本项目下载及运行的常见问 ...

  8. java中解密的思想_北大青鸟翔天解密,Java核心思想两大点

    Java已经成为一个庞大而复杂的技术平台,对于开发人员而言,要想更好的掌握Java技术,深入理解底层的技术处理细节必不可少.对核心概念和思想的掌握可以帮助我们举一反三.触类旁通,有助于提升我们对整个J ...

  9. java超出gc开销限制_超出了GC开销限制– Java堆分析

    java超出gc开销限制 这篇文章是我们原来的GC开销超出问题模式的延续. 正确的Java堆分析对于消除O​​utOfMemoryError:GC开销问题至关重要. 如果您不熟悉此Java HotSp ...

  10. java 存储过程返回结果集_通过SQL“select * from”从java存储过程返回结果集

    我可以直接通过SQL select * from语句从java存储过程(oracle)获取结果吗? 在数据库上,我将有一个java存储过程/函数,当它被调用时返回一个多列,多行结果集. 我想直接通过s ...

最新文章

  1. pfsense软路由防火墙(安装过程、L2tp配置)
  2. MATLAB数学计算与工程分析范例教程,MATLAB数学计算与工程分析范例教程
  3. KDD_cup99 pytorch
  4. linux java查看进程命令_linux一些查看进程情况的命令
  5. 对象 普通po转_谈谈C++对象的构造
  6. java中.of,java中的sizeof
  7. Codeforces Round #533 (Div. 2) C.思维dp D. 多源BFS
  8. php 对象赋值后改变成员变量影响赋值对象
  9. python动态执行语句_Python Language
  10. word无所不能之在word中浏览网页看电影
  11. pythonweb静态服务器_python实现外部静态服务器,浏览器通过HTTP与之通信2
  12. 互信息特征选择python_基于互信息的特征选择算法MATLAB实现
  13. Ultra Librarian 生成Orcad封装教程
  14. 关于“UDP转发被禁用”的解决办法
  15. 戴尔豪斯大学计算机科学学费,加拿大研究生申请案例:渥太华大学录取:电子商业科技申请案例【2013】...
  16. emacs ido模式
  17. Digital Asset与国际衍生品协会携手,布局智能合约在衍生品交易中的使用
  18. C++-STL(1)-Vector-随机数(randon、default_random_engine)
  19. pdfkit批量转换html文件为pdf
  20. 【Comet OJ - 2019国庆欢乐赛 F】 高速公路

热门文章

  1. Sql语句查询 显示序号
  2. BCH零确认和比特币RBF该怎么选?
  3. SLP是最近在BCH中引入的一个功能,它允许创建定制令牌。
  4. 二叉树的中序遍历(递归和非递归版本)
  5. 一键控制全屋设备,AI交互时代来临
  6. VS插件开发——格式化变量定义语句块
  7. 转帖 .Net(C#)纯GDI+绘制实时动态曲线图之二(曲线控件全部源码)
  8. (转)如何从storyBoard中加载其中一个controller
  9. UGUI世界转屏幕坐标
  10. Django models部分,数据库建立,错误解决