一,Read-Write Lock模式

在Read-Write Lock模式中,读取操作和写入操作是分开考虑的。在执行读取操作之前,线程必须获取用于读取的锁。
在执行写入操作之前,线程必须获取用于写入的锁。所以:
当一个线程在读取时,其他线程可以读取,但是不可以写入。
当一个线程正在写入时,其他线程不可以读取或写入。
因为执行互斥处理会降低程序的性能,但是如果把写入的互斥处理和读取的互斥处理分开来考虑,就可以提高系统性能

二,示例程序

public final class ReadWriteLock {
private int readingReaders = 0;//实际正在读取中的线程个数
private int waitingWriters = 0;//正在等待写入的线程个数
private int writingWriters = 0;//实际正在写入的线程个数
private boolean preferWriter = true;//若写入优先,则为true public synchronized void readLock()throws InterruptedException{
while (writingWriters > 0 || (preferWriter && waitingWriters > 0)){
wait();
}
readingReaders++;//正在读取的线程个数加1
} public synchronized void readUnlock(){
readingReaders--;//正在读取的线程个数减1
preferWriter = true;
notifyAll();
} public synchronized void writeLock()throws InterruptedException{
waitingWriters++;//等待写入的线程加1
try {
while (readingReaders > 0 || writingWriters > 0){
wait();
}
}finally {
waitingWriters--;//等待写入的线程减1
}
writingWriters++;//正在写入的线程加1
} public synchronized void writeUnlock(){
writingWriters--;//正在写入的线程减1
preferWriter = false;
notifyAll();
}
}
public class Data {
private final char[] buffer;
public final ReadWriteLock lock = new ReadWriteLock(); public Data(int size){
this.buffer = new char[size];
for (int i = 0; i < buffer.length; i++) {
buffer[i] = '*';
}
}
public char[] read()throws InterruptedException{
lock.readLock();
try {
return doRead();
}finally {
lock.readUnlock();
}
} /**
* 实际的读取操作,创建一个新的char数组newbuf,来复制buffer里的内容,并返回newbuf
* @return
*/
private char[] doRead(){
char[] newbuf = new char[buffer.length];
for (int i = 0; i < buffer.length; i++) {
newbuf[i] = buffer[i];
}
slowly();
return newbuf; } public void write(char c)throws InterruptedException{
lock.writeLock();
try {
doWrite(c);
}finally {
lock.writeUnlock();
}
} /**
* 实际的写入操作,每读取一个字符,就执行一次耗时操作。写入操作时间比读取操作时间长
* @param c
*/
public void doWrite(char c){
for (int i = 0; i < buffer.length; i++) {
buffer[i] = c;
slowly();
}
} /**
* 耗时操作,模拟处理业务逻辑
*/
public void slowly(){
try {
Thread.sleep(50);
}catch (InterruptedException e){ }
}
}
public class ReaderThread extends Thread {
private final Data data;
public ReaderThread(Data data){
this.data = data;
} @Override
public void run() {
try {
while (true){
char[] readbuf = data.read();
System.out.println(Thread.currentThread().getName()+" reads "+
String.valueOf(readbuf));
}
}catch (InterruptedException e){ }
}
}
public class WriterThread extends Thread {
private static final Random random = new Random();
private final Data data;
private final String filler;
private int index = 0;
public WriterThread(Data data,String filler){
this.data = data;
this.filler = filler;
} @Override
public void run() {
try {
while (true){
char c = nextchar();
data.write(c);
Thread.sleep(random.nextInt(3000));
}
}catch (InterruptedException e){ }
} private char nextchar(){
char c = filler.charAt(index);
index++;
if (index >= filler.length()){
index = 0;
}
return c;
}
}
public class Test {
public static void main(String[] args) {
Data data = new Data(10);
for (int i = 0; i < 6; i++) {
new ReaderThread(data).start();
} new WriterThread(data,"ABCDEFGHIJKLMNOPQRSTUVWXYZ").start();
new WriterThread(data,"abcdefghijklmnopqrstuvwxyz").start();
}
}

三,适用场景

1.读取操作频繁
2.读取频率比写入频率高

四,锁的含义

1.synchronized可以用于获取实例的锁,Java的每一个实例都持有一个锁,但同一个锁不能被两个以上的线程同时获取,
这种结构是Java编程规范规定的,java虚拟机也是这样实现的。这就是java提供的物理锁。
2.本章的 用于读取的锁 和 用于写入的锁,是开发人员自己实现的一种结构。这种锁是逻辑锁,我们可以通过修改ReadWriteLock类来改变锁的运行
ReadWriteLock类提供了用于 读取的锁 和 用于写入的锁 的这两个逻辑锁。但是用于实现这两个逻辑锁的物理锁只有一个,就是ReadWriteLock实例持有的锁

五,java.util.concurrent.locks.ReadWriteLock

java并发包提供了读写锁。

public class Data {
private final char[] buffer;
private final ReadWriteLock lock = new ReentrantReadWriteLock(true);
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock(); public Data(int size){
this.buffer = new char[size];
for (int i = 0; i < buffer.length; i++) {
buffer[i] = '*';
}
}
public char[] read()throws InterruptedException{ readLock.lock();
try {
return doRead();
}finally { readLock.unlock();
}
} /**
* 实际的读取操作,创建一个新的char数组newbuf,来复制buffer里的内容,并返回newbuf
* @return
*/
private char[] doRead(){
char[] newbuf = new char[buffer.length];
for (int i = 0; i < buffer.length; i++) {
newbuf[i] = buffer[i];
}
slowly();
return newbuf; } public void write(char c)throws InterruptedException{ writeLock.lock();
try {
doWrite(c);
}finally { writeLock.unlock();
}
} /**
* 实际的写入操作,每读取一个字符,就执行一次耗时操作。写入操作时间比读取操作时间长
* @param c
*/
public void doWrite(char c){
for (int i = 0; i < buffer.length; i++) {
buffer[i] = c;
slowly();
}
} /**
* 耗时操作,模拟处理业务逻辑
*/
public void slowly(){
try {
Thread.sleep(50);
}catch (InterruptedException e){ }
}
}

最新文章

  1. jQuery之常用且重要方法梳理(target,arguments,slice,substring,data,trigger,Attr)-(一)
  2. 托管项目到github
  3. 直关的sql 联级更新语句
  4. 安卓 DevOps:从一次推送命令到生产
  5. poj 2151 Check the difficulty of problems(概率dp)
  6. 【C/C++多线程编程之六】pthread相互排斥量
  7. ☀【jQuery插件】DOM 延迟渲染
  8. jQuery/CSS3实现图片层叠展开特效
  9. SQL 查找某个字段的首字母
  10. WdatePicker 日历控件使用方法+基本常用方法
  11. 【转】JavaScript中使用ActiveXObject操作本地文件夹的方法
  12. 分享一本书&lt;&lt;谁都不敢欺负你&gt;&gt;
  13. 谷歌。百度,阿里云,机器翻译简单PK。
  14. js一些格式化
  15. 外排序 External sorting
  16. OJ题解记录计划
  17. php面试中的经典问题
  18. meta中minimal-ui属性
  19. 微软Power BI 每月功能更新系列——6月Power BI 新功能学习
  20. jQuery实用Demo

热门文章

  1. spring cloud 实践之hystrix注意事项
  2. February 20th, 2018 Week 8th Tuesday
  3. 《Java大学教程》—第21章 高级案例研究
  4. 【Linux基础】crontab定时命令详解
  5. hdfs fsck命令查看HDFS文件对应的文件块信息(Block)和位置信息(Locations)
  6. Django-rest-framework 接口实现 Serializer 使用
  7. 7.01-beautiful_soup3
  8. TortoiseHg 学习笔记
  9. android与c#之间scoket获取数据进行赋值显示的问题
  10. 报错Unexpected token u