多线程学习之七读写锁
Read-Write Lock Pattern【读写】
一:Read-Write Lock Pattern的参与者
--->读写锁
--->数据(共享资源)
--->读线程
--->写线程
二Read-Write Lock Pattern模式什么时候使用
--->
* 为了多线线程环境下保护数据安全,我们必须避免的冲突
* 一个线程读取,另一个线程写入的read-write conflick
* 一个线程写入,另一个线程写入的write-write conflick
* 一个线程读取,另一个线程也在读取不会产生冲突
*
* 当线程想要获取读取锁定时:
* -->已经有线程在执行写入,则等待。不等待,则发生read-write conflick
* -->已经有线程在读取,则不需要等待。不存在read-read conflick
*
* 当线程想要获取写入锁定时:
* -->已经有线程在执行写入,则等待。不等待,则发生write-write conflick
* -->已经有线程在执行读取,则等待。不等待,则发生read-write conflick
--->利用同时(读取)不会引起数据冲突的特性,提高系统的性能
--->适合读取操作繁重时
--->适合读取操作比写入操作繁重时
三:Read-Write Lock Pattern思考
--->
四进阶说明
--->
读写锁
/** * */ package com.benxq.thread8; /** * 读写锁 * Created by qucf on 2015年10月23日. */ public class ReadWriteLock { //正在读取的线程个数 private Integer readInteger=0; //正在写入线程的个数(最大为1) private Integer writeInteger=0; //正在等待获取写入锁定的线程个数 private Integer writeWaitInteger=0; //获取写入锁定优先的话 设置为true private boolean writeBoolean=false; //获取读取锁的方法 public synchronized void readlock() throws InterruptedException{ //如果有写入操作 写入优先并且有等待写入的线程 while(writeInteger>0 ||(writeWaitInteger>0&&writeBoolean)){ wait(); } readInteger++; } //释放读取锁的方法 public synchronized void readUnLock(){ //读取减1 readInteger--; //将写入设置优先 writeBoolean=true; //唤醒所有线程 notifyAll(); } //获取写入锁定的方法 public synchronized void writeLock() throws InterruptedException{ writeWaitInteger++; //如果有读线程或者写线程则等待 try { while(readInteger>0||writeInteger>0){ wait(); } } finally{ writeWaitInteger--; } //写入线程+1 writeInteger++; } //释放写入锁 public synchronized void writeUnLock(){ //写入线程数-1 writeInteger--; //设置优先级为false writeBoolean=false; //唤醒所有线程 notifyAll(); } }
数据类
/** * */ package com.benxq.thread8; /** * 数据类 * 持有公共数据+改公共数据的读写锁 * Created by qucf on 2015年10月23日. */ public class Data { //数据类持有的锁 private final ReadWriteLock lock=new ReadWriteLock(); //要访问的公共数据 private final String[] buffer; public Data(int i) { buffer=new String[i]; for (int a = 0; a < buffer.length; a++) { buffer[a]="**"; } } public ReadWriteLock getLock() { return lock; } //读取数据的方法 public String[] read() throws InterruptedException{ //获取读取锁 lock.readlock(); try { Thread.sleep(1000); return buffer; } finally{ lock.readUnLock(); } } //写入操作 public void write(String a) throws InterruptedException { //获取写入的suo lock.writeLock(); try { Thread.sleep(1000); doWrite(a); } finally{ lock.writeUnLock(); } } //真正的写操作 public void doWrite(String a){ for (int i = 0; i < buffer.length; i++) { buffer[i]=a; } } }
读线程
/** * */ package com.benxq.thread8; /** * 读线程 * Created by qucf on 2015年10月23日. */ public class ReadThread implements Runnable{ private Data data; public ReadThread(Data data) { this.data=data; } @Override public void run() { while(true){ try { String[] str = data.read(); Thread.sleep(1000); System.out.println("["+Thread.currentThread().getName()+"]读取数据为:"+str[0]); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
写线程
/** * */ package com.benxq.thread8; /** * 写线程 * Created by qucf on 2015年10月23日. */ public class WriteThread implements Runnable{ private Data data; public WriteThread(Data data) { this.data=data; } @Override public void run() { while(true){ try { for (int i = 0; i < 10; i++) { data.write("内容"+i); Thread.sleep(1000); System.out.println("["+Thread.currentThread().getName()+"]写入内容为:内容"+i); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
主线程
/** * */ package com.benxq.thread8; /** * Created by qucf on 2015年10月23日. */ public class Test { public static void main(String[] args) { //生命公共数据 Data data=new Data(3); //生命读取线程 Thread r1=new Thread(new ReadThread(data)); Thread r2=new Thread(new ReadThread(data)); Thread r3=new Thread(new ReadThread(data)); //声明写入线程 Thread w1=new Thread(new WriteThread(data)); Thread w2=new Thread(new WriteThread(data)); Thread w3=new Thread(new WriteThread(data)); r1.start(); r2.start(); r3.start(); w1.start(); w2.start(); w3.start(); } }