第六章 Read-Write Lock模式 大家一起读没问题,但读的时候不要写

【Read-Write Lock模式】当线程读取实例的状态时,实例的状态不会发生变化。实例的状态仅在线程执行“写入”操作时才会发生变化。在Read-Write Lock模式中,读取操作和写入操作是分开考虑的。在执行读取操作之前,线程必须获取用于读取的锁。而在执行写入操作之前,线程必须获取用于希尔的锁。

由于当线程执行读取操作时,实例的状态不会发生变化,所以多个线程可以同时读取。但在读取时,不可以写入。

当线程执行写入操作时,实例的状态就会发生变化。因此当有一个线程正在写入时,其他线程不可以读取或写入。

【示例程序】

名字

说明

Main

测试程序行为的类

Data

可以读写的类

WriterThread

表示写入线程的类

ReadThread

表示读取线程的类

ReadWriteLock

提供读写锁的类

Main类

public class Main {

     public static void main(String[] args) {

          Data data = new Data(10);

          new ReaderThread(data).start();

          new ReaderThread(data).start();

          new ReaderThread(data).start();

          new ReaderThread(data).start();

          new ReaderThread(data).start();

          new ReaderThread(data).start();

          new WriterThread(data, "ABCDEFGHIJKLMN").start();

          new WriterThread(data, "abcdefghijklmn").start();

     }    

}

Data类

public class Data {

     private final char[] buffer;

     private 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();

          }

     }

     public void write(char c) throws InterruptedException {

          lock.writeLock();

          try {

              doWrite(c);

          } finally {

              lock.writeUnlock();

          }

     }

     private char[] doRead() {

          char[] newbuf = new char[buffer.length];

          for(int i=0;i<buffer.length;i++) {

              newbuf[i]=buffer[i];

          }

          slowly();

          return newbuf;

     }

     private void doWrite(char c) {

          for(int i=0;i<buffer.length;i++) {

              buffer[i]=c;

              slowly();

          }

     }

     private void slowly() {

          try {

              Thread.sleep(50);

          } catch(InterruptedException e){}

     }

}

WriterThread类

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;

     }

     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;

     }

}

ReaderThread类

public class ReaderThread extends Thread {

     private final Data data;

     

     public ReaderThread(Data data){

          this.data=data;

     }

     public void run(){

          try{

              while(true){

                   char[] readbuf=data.read();

                   System.out.println(Thread.currentThread().getName()+" reads "+String.valueOf(readbuf));

              }

          }catch(InterruptedException e){}

     }

}

ReadWriterLock类

public class ReadWriteLock {

     private int readingReaders = 0;//实际正在读取中的线程个数

     private int waitingWriters = 0;//正在等待写入的线程个数

     private int writingReaders = 0;//实际正在写入的线程个数

     private boolean preferWriter = true;//若写入优先,则为true

     

     public synchronized void readLock() throws InterruptedException {

          while(writingReaders > 0 || (preferWriter && waitingWriters > 0)) {

              wait();

          }

          readingReaders++;

     }

     public synchronized void readUnlock() {

          readingReaders--;

          preferWriter = true;

          notifyAll();

     }

     public synchronized void writeLock() throws InterruptedException {

          waitingWriters++;

          try {

              while(readingReaders>0||writingReaders>0){

                   wait();

              }

          }finally{

              waitingWriters--;

          }

          writingReaders++;

     }

     public synchronized void writeUnlock() {

          writingReaders--;

          preferWriter = false;

          notifyAll();

     }

}

【守护条件的确认】

readLock方法

在线程开始实际的读取操作之前,readLock方法就会被调用。当线程从该方法返回后,便可开始执行实际的读取操作。

当线程开始执行实际的读取操作时,有其他线程正在执行读取操作也没关系,但不可以存在正在执行写入操作的线程。因为当有线程正在执行写入操作时,如果开始执行读取操作,便会引起read-write conflict。因此守护条件是“没有线程正在执行写入操作”。

writingReaders<=0

 

writeLock方法

在线程开始实际的写入操作之前,writeLock方法就会被调用。当线程从该方法返回后,便可开始执行实际的写入操作。

如果有线程正在执行读取操作,便会引起read-write conflict;如果有线程正在执行写入操作,便会引起write-write conflict。因此守护条件为“没有线程正在执行读取操作或写入操作”

readingReaders<=0&&writingReaders<=0

 

【Read-Write Lock模式中登场的角色】

1Reader读者

    Reader角色对SharedResource角色执行read操作。

2.Writer写者

    Writer角色对SharedResource角色执行write操作。

3.ShareRescource共享资源

    ShareRescource角色表示的是Reader角色和Writer角色二者共享的资源。ShareRescource角色提供不修改内部状态的操作read和修改内部状态的操作write。

4.ReadWriteLock读写锁

    ReadWriteLock角色提供了ShareRescource角色实现read操作和write操作时所需的锁。

 

【锁的含义】

    synchronized可以用于获取实例的锁。Java的每一个实例都持有一个锁,但同一个锁不可以由两个以上的线程同时获取。这是所谓的物理锁。

    用于读取的锁和用于写入的锁所指的锁与使用synchronized获取的锁是不一样的。逻辑锁。开发人员可以通过修改ReadWriteLock来改变锁的运行。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值