在java多线程中,为了提高效率有些共享资源允许同时进行多个读的操作,但只允许一个写的操作,比如一个文件,只要其内容不变可以让多个线程同时读,不必做排他的锁定,排他的锁定只有在写的时候需要,以保证别的线程不会看到数据不完整的文件。

   下面是个关于多线程读写锁的例子,我稍微做了下修改,蛮容易理解的,来至于http://www.highya.com/redirect.php?fid=113&tid=7180&goto=nextoldset。

这里模拟了这样一个场景: 在ReadWriteLockOperator对象里设置一个共享资源 shareResources 。

有3个读者(A, B, C)一直连续的从 shareResources 获取信息, 然后输出到控制台 ;有一个作者每隔60秒往shareResources 加入信息, 加信息的过程相对耗时, 在这段时间, 任何读者都不能访问 shareResources。

  写了4个类来验证这种情况,只在windows下做了测试。

  ReadTask.java       读任务

  WriteTask.java      写任务

  ReadWriteLockLogic.java     读写操作的逻辑

  ReadWriteLockTest.java      带有main方法的测试类

---------------------------------------混哥线-----------------------------------------------    

public         class         ReadTask         extends         Thread {       
                //logic bean       
                private         ReadWriteLockLogic readWriteLockOperator;       
                //读者       
                private         String reader;       
                public         ReadTask(ReadWriteLockLogic readWriteLockOperator, String reader) {       
                this        .readWriteLockOperator = readWriteLockOperator;       
                this        .reader = reader;       
                }       
                private         ReadTask(){}       
                // 执行任务       
                public         void         run() {       
                if        (        this        .readWriteLockOperator !=         null        ){       
                try         {       
                while        (!isInterrupted()){       
                Thread.sleep(        200        );       
                System.out.println(reader +         " read:"        
                + Thread.currentThread().toString() +         " : "         +         this        .readWriteLockOperator.read());       
                }       
                }         catch         (Exception e) {       
                // TODO: handle exception       
                }       
                }       
                }       
        }

-------------------------------------------------------------------------------------

public         class         WriteTask          extends         Thread{       
                //logic bean       
                private         ReadWriteLockLogic readWriteLockOperator;       
                //作者       
                private         String writer;       
                public         WriteTask(ReadWriteLockLogic readWriteLockOperator, String writer) {       
                this        .readWriteLockOperator = readWriteLockOperator;       
                this        .writer = writer;       
                }       
                private         WriteTask(){}       
                // 一个很耗时的写任务       
                public         void         run() {       
                try         {       
                while        (!isInterrupted()){       
                Thread.sleep(        100        );       
                this        .readWriteLockOperator.write(        this        .writer,         "hehehhe"        );       
                }       
                }         catch         (Exception e) {       
                // TODO: handle exception       
                }       
                }       
        }

----------------------------------------------------------------------------------

import         java.util.ArrayList;       
        import         java.util.List;       
        import         java.util.concurrent.locks.Lock;       
        import         java.util.concurrent.locks.ReadWriteLock;       
        import         java.util.concurrent.locks.ReentrantReadWriteLock;       
        //读写操作的逻辑       
        public         class         ReadWriteLockLogic {       
                // 初始化一个 ReadWriteLock       
                private         ReadWriteLock lock =         new         ReentrantReadWriteLock();       
                //共享资源       
                private         List<String> shareResources =         new         ArrayList<String>(        0        );       
                //读       
                public         String read() {       
                // 得到 readLock 并锁定       
                Lock readLock = lock.readLock();       
                readLock.lock();       
                try         {       
                // 读相对省时,做空循环 大约0.5second       
                for        (        int         i=        0         ;i<        2500000        ; i++){       
                System.out.print(        ""        );       
                }       
                // 做读的工作       
                StringBuffer buffer =         new         StringBuffer();       
                for         (String shareResource : shareResources) {       
                buffer.append(shareResource);       
                buffer.append(        "\t"        );             
                }       
                return         buffer.toString();       
                }         finally         {       
                readLock.unlock();        //一定要保证锁的释放       
                }       
                }       
                //写       
                public         void         write(String writer, String content) {       
                // 得到 writeLock 并锁定       
                Lock writeLock = lock.writeLock();       
                writeLock.lock();       
                try         {       
                System.out.println(writer +         " write ==="         + Thread.currentThread().toString());       
                // 写比较费时,所以做空循环 大约13second       
                for        (        int         i=        0         ;i<        10000000        ; i++){       
                System.out.print(        ""        );       
                System.out.print(        ""        );       
                }       
                
                // 做写的工作       
                int         count = shareResources.size();       
                for         (        int         i=count; i < count +         1        ; i++) {       
                shareResources.add(content +         "_"         + i);       
                }       
                }         finally         {       
                writeLock.unlock();        //一定要保证锁的释放       
                }       
                }       
        }

------------------------------------------------------------------------------------

import         java.util.concurrent.ExecutionException;       
        import         java.util.concurrent.Executors;       
        import         java.util.concurrent.ScheduledExecutorService;       
        import         java.util.concurrent.TimeUnit;       
        public         class         ReadWriteLockTest {       
                public         static         void         main(String[] args)         throws         InterruptedException, ExecutionException {       
                //1 创建一个具有排程功能的线程池       
                ScheduledExecutorService service = Executors.newScheduledThreadPool(        5        );       
                //2 读写锁的logic bean       
                ReadWriteLockLogic lockOperator =         new         ReadWriteLockLogic();       
                //3 生成一个可执行任务(该任务执行完毕可以返回结果 或者 抛出异常;而Runnable接口的run方法则不行)       
                Runnable writeTask1 =         new         WriteTask(lockOperator,         "作者A"        );       
                //4 延时0秒后每2秒重复执行writeTask1;       
                service.scheduleAtFixedRate(writeTask1,         0        ,         60        , TimeUnit.SECONDS);       
                //5 创建3个读任务       
                Runnable readTask1 =         new         WriteTask(lockOperator,         "作者B"        );       
                Runnable readTask2 =         new         ReadTask(lockOperator,         "读者B"        );       
                Runnable readTask3 =         new         ReadTask(lockOperator,         "读者C"        );       
                //6 延时0秒后每秒执行一次task1;       
                service.scheduleAtFixedRate(readTask1,         1        ,         1        , TimeUnit.SECONDS);       
                service.scheduleAtFixedRate(readTask2,         2        ,         1        , TimeUnit.SECONDS);       
                service.scheduleAtFixedRate(readTask3,         3        ,         1        , TimeUnit.SECONDS);       
                
                }       
        }

----------------------------------------------------------------------------------------

作者A write ===Thread[pool-1-thread-1,5,main]

作者B write ===Thread[pool-1-thread-4,5,main]

读者C read:Thread[pool-1-thread-3,5,main] : hehehhe_0 hehehhe_1 

读者B read:Thread[pool-1-thread-2,5,main] : hehehhe_0 hehehhe_1

作者A write ===Thread[pool-1-thread-1,5,main]

................

通过观察控制台,可以看到作者a出现后,大约5秒作者b才会出现,而又过了5秒后,读者c和读者b同时会出现,接着5秒后,作者a又出现了。这说明了,读锁之间没有排斥,可以多线程持有并且排斥WriteLock的持有线程。而WriteLock是全部排斥的,是独占的,比较独!

 

下面是附赠的读写锁的小知识,来至http://www.txdnet.cn/essay/view.jsp?tid=1288670091703&cid=2

(a).重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想.

(b).WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的持有.反过来ReadLock想要升级为WriteLock则不可能,为什么?参看(a),呵呵.

(c).ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥.这一特性最为重要,因为对于高读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量.

(d).不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致.

(e).WriteLock支持Condition并且与ReentrantLock语义一致,而ReadLock则不能使用Condition,否则抛出UnsupportedOperationException异常.