java多线程ReadwriteLock

    技术2022-05-11  41

    本文转载自:http://blog.csdn.net/doudou_bb_08/

    1. 模式描述:大家想看就看把, 但是看的时候不能写哦.Read-Write Lock Pattern将读取与写入分开处理. 在读取数据之前,必须获取用来读取的锁定.而要写入的时候,则必须获取用来写入的锁定.因为读取的时候,实例的状态不会改变,所以,就算有多个线程在同时读取也没有关系.但,有人在读取的时候,不可做写入的操作.写入的时候,实例的状态就会改变,于是,当有一个线程在写入的时候,其他的线程不可以进行读取或写入.一般来说,进行共享互斥会使程序性能变差,但将写入的共享互斥与读取的共享互斥分开思考,就可以提升程序的性能.2. 参与者:2.1. Reader(读取者)参与者.2.2. Writer(写入者)参与者.2.3. SharedResource(共享资源)参与者.2.4. ReadWriteLock(读写用锁定)参与者.3. 示例程序:3.1 ShareResource类 - SharedResource(共享资源)参与者:

    package  com.quf.study.thread.readwritelock; import  java.io.Serializable; /** * <strong>Title : ShareResource<br></strong> * <strong>Description : </strong>共享数据实体类.<br>  * <strong>Create on : 2008-4-30<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人        修改日期        修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public   final   class  ShareResource  implements  Serializable  {    /**     * <code>serialVersionUID</code>-注释     */    private static final long serialVersionUID = 235799050473308166L;        /**     * <code>m_buf</code>-数据.     */    private final char[] m_buf;        /**     * <code>m_lock</code>-读写锁.     */    private final ReadWriteLock m_lock = new ReadWriteLock(true);        /**     * 构造函数     */    public ShareResource(int size) {        // TODO Auto-generated constructor stub        this.m_buf = new char[size];        for ( int i = 0 ; i < this.m_buf.length ;i++ ) {            this.m_buf[i] = '*';        }    }        /**     * 读取数据.     * <br>     * 该方法中使用了before/after模式     * <pre>     *    before操作;     *         *    try{     *         *       execute();     *            *    }finally{     *         *       after操作;     *            *    }     * </pre>     * @return 数据数组.     */    public char[] read() throws InterruptedException{                //申请读取锁定.        this.m_lock.readLock();                try {            return this.doRead();                    } finally {                        this.m_lock.readUnLock();        }    }        /**     * 写入数据.     * @param data - 要写入的数据.     */    public void write(char data) throws InterruptedException{                //申请写入锁定.        //this.m_lock.writeLock();                try {            this.m_lock.writeLock();            this.doWrite(data);        } finally {            this.m_lock.writeUnLock();        }    }        /**     * 读取数据.     * @return 数据集合.     */    private char[] doRead(){                char[] t_newBuf = new char[this.m_buf.length];                for ( int i = 0 ; i < this.m_buf.length ; i++ ) {            t_newBuf[i] = this.m_buf[i];        }                this.doSlowly();                return t_newBuf;    }        /**     * 写入数据.     * @param data - 写入的数据.     */    private void doWrite(char data){                for ( int i = 0 ; i < this.m_buf.length ;i++ ) {            this.m_buf[i] = data;            this.doSlowly();        }    }        /**     * 线程休眠.     */    private void doSlowly(){        try {                        Thread.sleep(50);                    } catch (InterruptedException e) {            // TODO: handle exception        }    }} // END CLASS OF Data.

    3.2 ReadWriteLock类 - 读写锁:

    package  com.quf.study.thread.readwritelock; import  java.io.Serializable; /** * <strong>Title : ReadWriteLock<br></strong> * <strong>Description : </strong>读写锁类.<br> * <pre> * 为了保护安全性,必须防止以下两种冲突: * 1. 读取和写入冲突. * 2. 写入和写入冲突. *  * 为了达到以上的保护,可以获取读取锁定,写入锁定的条件有以下4种情况: * 1. 当线程想获取访问的锁定时........ *    <1>已经有线程正在写入时,等待. *       理由: 不等待的话,会引起read-write conflict. *    <2>已经有线程在进行读取时,不等代. *       理由: read-read不会造成conflict. * 2. 当线程想要获取写入用的锁定时: *    <3>已经有线程在进行写入时,等待. *       理由: 不等待的话,会引起write-write conflict. *    <4>已经有线程在进行读取时,等待. *       理由: 不等待的话, 会引起read-write conflict. * </pre> * <strong>Create on : 2008-4-30<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人        修改日期        修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public   final   class  ReadWriteLock  implements  Serializable  {    /**     * <code>serialVersionUID</code>-注释     */    private static final long serialVersionUID = -6877946865095666037L;        /**     * <code>m_readingReaders</code>-正在进行读取操作的线程数量.     */    private int m_readingReaders;        /**     * <code>m_waitingWriters</code>-正在等待写操作的线程数量.     */    private int m_waitingWriters;        /**     * <code>m_writingWriters</code>-正在进行写操作的线程数量.     */    private int m_writingWriters;        /**     * <code>m_preferWrite</code>-是否优先写操作标志.true - 优先写操作,false - 正常顺序.     */    private boolean m_preferWrite;        /**     * 构造函数     * @param preferWrite-是否优先写操作标志.true - 优先写操作,false - 正常顺序.     */    public ReadWriteLock(boolean preferWrite) {        // TODO Auto-generated constructor stub        this.m_preferWrite = preferWrite;    }        /**     * 获取读取锁.     * @throws InterruptedException     */    public synchronized void readLock() throws InterruptedException {                //如果正在写入的线程数>0 或者 (写优先 并且 等待写入的线程数 > 0 ) 则等待.        if ( this.m_writingWriters > 0 || (this.m_preferWrite && this.m_waitingWriters > 0 ) ) {            wait();        }                this.m_readingReaders++;    }        /**     * 释放读取锁.     * @throws InterruptedException     */    public synchronized void readUnLock() throws InterruptedException{                this.m_readingReaders--;        this.m_preferWrite = true;        notifyAll();    }        /**     * 获取写入锁.     * @throws InterruptedException     */    public synchronized void writeLock() throws InterruptedException{                //正在等待写入的计数器+1.        this.m_waitingWriters++;                try {                        //如果 ( 正在读取的线程数 > 0 或者 正在写入的线程数 > 0 ) 则等待.            if ( this.m_readingReaders > 0 || this.m_writingWriters > 0 ) {                wait();            }        } finally {                        this.m_waitingWriters--;        }                this.m_writingWriters++;    }        /**     * 释放写入锁.     * @throws InterruptedException     */    public synchronized void writeUnLock() throws InterruptedException{        this.m_writingWriters--;        this.m_preferWrite = false;        notifyAll();    }        } // END CLASS OF ReadWriteLock.

    3.3 ReadDataThread - 读取数据的线程类:

    package  com.quf.study.thread.readwritelock; /** * <strong>Title : ReaderThread<br></strong> * <strong>Description : </strong>读取数据的线程.<br>  * <strong>Create on : 2008-5-4<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人        修改日期        修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public   final   class  ReadDataThread  extends  Thread  {        /**     * <code>m_data</code>-注释     */    private final ShareResource m_data;        /**     * 构造函数     * @param data     */    public ReadDataThread(ShareResource data) {        this.m_data = data;    }        /* (non-Javadoc)     * @see java.lang.Thread#run()     */    public void run(){                try {            while( true ) {                char[] t_readBuf = this.m_data.read();                                System.out.println(Thread.currentThread().getName()+" reads "+String.valueOf(t_readBuf) );            }        } catch (InterruptedException e) {            // TODO: handle exception        }            }} // END CLASS OF ReadDataThread.

    3.4 WriteDataThread - 写入数据的线程类:

    package  com.quf.study.thread.readwritelock; import  java.util.Random; /** * <strong>Title : WriteDataThread<br></strong> * <strong>Description : </strong>写数据的线程.<br>  * <strong>Create on : 2008-5-4<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人        修改日期        修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public   final   class  WriteDataThread  extends  Thread  {        /**     * <code>s_random</code>-注释     */    public static final Random s_random = new Random();        /**     * <code>m_data</code>-注释     */    private final ShareResource m_data;        /**     * <code>m_filter</code>-注释     */    private final String m_filter;        /**     * <code>m_index</code>-注释     */    private int m_index;        /**     * 构造函数     * @param data     * @param filter     */    public WriteDataThread(ShareResource data,String filter){        this.m_data = data;        this.m_filter = filter;    }        /* (non-Javadoc)     * @see java.lang.Thread#run()     */    public void run() {        try {            while ( true ) {                char t_data = this.nextChar();                                this.m_data.write(t_data);                                Thread.sleep(s_random.nextInt(3000));                            }        } catch (InterruptedException ie) {        }    }        /**     * 获取下一个字符.     * @return 下一个字符.     */    private char nextChar() {                char t_c = this.m_filter.charAt(this.m_index);                this.m_index++;                if ( this.m_index >= this.m_filter.length() ) {            this.m_index = 0 ;         }                return t_c;    }} // END CLASS OF WriteDataThread.

    3.5 ReadWriteLockTest - 测试类:

    package  com.quf.study.thread.readwritelock; /** * <strong>Title : ReadWriteLockTest<br></strong> * <strong>Description : </strong>读写锁测试类.<br>  * <strong>Create on : 2008-5-4<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人        修改日期        修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public   final   class  ReadWriteLockTest  {        public static void main(String[] args ) {                //创建数据对象.        ShareResource t_data = new ShareResource(10);                new ReadDataThread(t_data).start();        new ReadDataThread(t_data).start();        new ReadDataThread(t_data).start();        new ReadDataThread(t_data).start();        new ReadDataThread(t_data).start();        new ReadDataThread(t_data).start();                new WriteDataThread(t_data,"ABCDEFGHIJKLMNOPQRSTUVWXYZ").start();        new WriteDataThread(t_data,"abcdefghijklmnopqrstuvwxyz").start();            }    } // END CLASS OF ReadWriteLockTest.

    4. 扩展思考方向:4.1 该模式利用同时读取而不会产生冲突的特性,提高了程序的性能.4.2 该模式适合读取操作比较繁重的情况.4.3 该模式适合读取比写入操作频繁时.4.4 锁定的意义:

    使用synchronized,可以获取实例的锁定.Java程序的每个实例各有一个"锁定",同一个实 例的锁定无法由两个以上的线程所获取.这是制定在JAVA语言规格里,实现在Java执行环 境里的机制.故称为物理性的锁定.Java程序无法去改变这种锁定的行为.

    5. 相关知识:4.1 Before/After Pattern:前置处理(获取锁定)try{实际的操作.} finally {后续处理

    (解除锁定)}


    最新回复(0)