java自己实现读写锁_关于读写锁算法的Java实现及思考
问题背景:多个线程对一个共享的资源进行读写访问。写线程之间需要互斥,读线程跟写线程需要互斥,读线程之间不用互斥。
早些时候听张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实现及思考相关推荐
- java 实现队列读写锁_史上最全的Java并发系列之Java中的锁的使用和实现介绍(二)...
前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger 种一棵树最好的时间是十年前,其次是现在 絮叨 上节是锁的第一 ...
- java内存中读文件_关于内存管理:读取Java中的大文件
我需要一个非常了解Java和内存问题的人的建议. 我有一个大文件(大约1.5GB),我需要将此文件切成许多小文件(例如100个小文件). 我通常知道如何做到这一点(使用BufferedReader), ...
- java 多线程 并发 面试题_最常见的15个Java多线程,并发面试问题
假设你有三个线程T1,T2,T3.你如何能保证线程T2在线程T1后运行,T3在T2后运行 这个线程面试问题大多是在第一轮或电话筛选轮次中会被问到的,这个多线程问题的目的是检查候选人对"joi ...
- 用Java代码实现日志记录器_如何在此简单的Java日志记录实现中附加到日志文件? - java...
我得到了以下用于创建和管理Logger的类.每当执行代码和程序时,都会使用对静态getLogger()捕获块的调用进行记录. public class Log { private static fin ...
- java能调用python吗_如何使用运行时在Java中调用python程序 - java
我想用来自Java的参数调用python程序.但是我的输出是空白.代码在这里. Python代码在这里: import sys print(sys.argv[1]) Java代码在这里: public ...
- java虚拟机内存模型种类_深入理解volatile类型——从Java虚拟机内存模型角度
一.前言 在java多线程编程中,volatile可以用来定义轻量级的共享变量,它比synchronized的使用成本更低,因为它不会引起线程上下文的切换和调度.所谓知己知彼.百战不殆.本文从JVM内 ...
- java实现 k nn算法_数据挖掘(二)——Knn算法的java实现
本文接数据挖掘-基于Kmeans算法.MBSAS算法及DBSCAN算法的newsgroup18828文本聚类器的JAVA实现(上). (update 2012.12.28 关于本项目下载及运行的常见问 ...
- java中解密的思想_北大青鸟翔天解密,Java核心思想两大点
Java已经成为一个庞大而复杂的技术平台,对于开发人员而言,要想更好的掌握Java技术,深入理解底层的技术处理细节必不可少.对核心概念和思想的掌握可以帮助我们举一反三.触类旁通,有助于提升我们对整个J ...
- java超出gc开销限制_超出了GC开销限制– Java堆分析
java超出gc开销限制 这篇文章是我们原来的GC开销超出问题模式的延续. 正确的Java堆分析对于消除OutOfMemoryError:GC开销问题至关重要. 如果您不熟悉此Java HotSp ...
- java 存储过程返回结果集_通过SQL“select * from”从java存储过程返回结果集
我可以直接通过SQL select * from语句从java存储过程(oracle)获取结果吗? 在数据库上,我将有一个java存储过程/函数,当它被调用时返回一个多列,多行结果集. 我想直接通过s ...
最新文章
- pfsense软路由防火墙(安装过程、L2tp配置)
- MATLAB数学计算与工程分析范例教程,MATLAB数学计算与工程分析范例教程
- KDD_cup99 pytorch
- linux java查看进程命令_linux一些查看进程情况的命令
- 对象 普通po转_谈谈C++对象的构造
- java中.of,java中的sizeof
- Codeforces Round #533 (Div. 2) C.思维dp D. 多源BFS
- php 对象赋值后改变成员变量影响赋值对象
- python动态执行语句_Python Language
- word无所不能之在word中浏览网页看电影
- pythonweb静态服务器_python实现外部静态服务器,浏览器通过HTTP与之通信2
- 互信息特征选择python_基于互信息的特征选择算法MATLAB实现
- Ultra Librarian 生成Orcad封装教程
- 关于“UDP转发被禁用”的解决办法
- 戴尔豪斯大学计算机科学学费,加拿大研究生申请案例:渥太华大学录取:电子商业科技申请案例【2013】...
- emacs ido模式
- Digital Asset与国际衍生品协会携手,布局智能合约在衍生品交易中的使用
- C++-STL(1)-Vector-随机数(randon、default_random_engine)
- pdfkit批量转换html文件为pdf
- 【Comet OJ - 2019国庆欢乐赛 F】 高速公路