美文网首页
Java中线程同步(五):ReentrantReadWriteL

Java中线程同步(五):ReentrantReadWriteL

作者: DON_1007 | 来源:发表于2017-03-09 16:59 被阅读0次

ReentrantReadWriteLock是对ReadWriteLock接口的一个具体实现。ReadWriteLock接口中只自定义了两个方法

  • Lock readLock();
  • Lock writeLock();

对应着一个读取锁和一个写入锁。多个线程并发访问同一个ReadWriteLock是读写互斥,写写互斥,读读共享。
假设现在有两个线程 A 和 B,A先执行,那么在同一把锁的情况下

A B 状态
读 或 写 阻塞
阻塞
共享

代码示例:A写B读,B阻塞

 private class ThreadA extends Thread{
        @Override
        public void run() {
            super.run();

                readWriteLock.writeLock().lock();//写锁
                Log.e(TAG,getClass().getSimpleName() + " start mCurrentValue =  " + mCurrentValue);
                try {
                    Thread.sleep(2000);//线程沉睡2秒
                    mCurrentValue ++; //修改mCurrentValue的值
                }catch (Exception e){
                    e.printStackTrace();
                }
                Log.e(TAG,getClass().getSimpleName() + " end mCurrentValue =  " + mCurrentValue);
                readWriteLock.writeLock().unlock();

        }
    }

    private class ThreadB extends Thread{
        @Override
        public void run() {
            super.run();
                readWriteLock.readLock().lock();//读锁
                Log.e(TAG, getClass().getSimpleName() + " start mCurrentValue =  " + mCurrentValue);
                try {
                    Thread.sleep(2000);//线程沉睡2秒
                }catch (Exception e){
                    e.printStackTrace();
                }
                Log.e(TAG,getClass().getSimpleName() + " end mCurrentValue =  " + mCurrentValue);
                readWriteLock.readLock().unlock();
        }
    }
03-09 16:26:34.174 16667-16685/? E/ReadWriteLockFragment: ThreadA start mCurrentValue =  0 
//线程A启动,获取 写入锁 成功,开始执行任务
03-09 16:26:36.177 16667-16685/? E/ReadWriteLockFragment: ThreadA end mCurrentValue =  1  
//2秒之后,修改变量值,线程A解锁
03-09 16:26:36.178 16667-16686/? E/ReadWriteLockFragment: ThreadB start mCurrentValue =  1 
//在线程A的解除写入锁后,线程B启动
03-09 16:26:38.180 16667-16686/? E/ReadWriteLockFragment: ThreadB end mCurrentValue =  1  
//线程B运行完成,解锁

上面可以看到线程B发生了阻塞,一直到线程A解锁之后,线程B才开始执行任务,通过mCurrentValue的值也可以看出,在线程B中打印的mCurrentValue 的值都为1

1、代码示例:A写B写,B阻塞

修改`ThreadB`的代码

private class ThreadB extends Thread{
        @Override
        public void run() {
            super.run();
                readWriteLock.writeLock().lock();//写锁
                Log.e(TAG, getClass().getSimpleName() + " start mCurrentValue =  " + mCurrentValue);
                try {
                    Thread.sleep(2000);//线程沉睡2秒
                    mCurrentValue ++; //修改mCurrentValue的值
                }catch (Exception e){
                    e.printStackTrace();
                }
                Log.e(TAG,getClass().getSimpleName() + " end mCurrentValue =  " + mCurrentValue);
                readWriteLock.writeLock().unlock();
        }
    }

再次运行,分析log信息

03-09 16:34:18.873 17052-17068/? E/ReadWriteLockFragment: ThreadA start mCurrentValue =  0 
//线程A启动,获取写入锁,开始执行任务
03-09 16:34:20.874 17052-17068/? E/ReadWriteLockFragment: ThreadA end mCurrentValue =  1 
//线程A执行任务完毕,变量值0+1=1,解锁
03-09 16:34:20.875 17052-17069/? E/ReadWriteLockFragment: ThreadB start mCurrentValue =  1  
//线程B在A解锁之后获取锁成功,开始执行任务
03-09 16:34:22.877 17052-17069/? E/ReadWriteLockFragment: ThreadB end mCurrentValue =  2  
//线程B执行任务完毕,变量值1+1=2,解锁

上面可以看到在A线程执行任务的时候,B线程是阻塞的。一直到A线程解锁,B线程才开始执行任务。

2、代码示例:A读B写,B阻塞

修改TheadA代码

private class ThreadA extends Thread{
        @Override
        public void run() {
            super.run();

                readWriteLock.readLock().lock();//读锁
                Log.e(TAG,getClass().getSimpleName() + " start mCurrentValue =  " + mCurrentValue);
                try {
                    Thread.sleep(2000);//线程沉睡2秒
                }catch (Exception e){
                    e.printStackTrace();
                }
                Log.e(TAG,getClass().getSimpleName() + " end mCurrentValue =  " + mCurrentValue);
                readWriteLock.readLock().unlock();

        }
    }

再次运行,分析log信息

03-09 16:40:27.390 17252-17302/? E/ReadWriteLockFragment: ThreadA start mCurrentValue =  0
//A线程启动,获取读锁成功,开始执行
03-09 16:40:29.391 17252-17302/? E/ReadWriteLockFragment: ThreadA end mCurrentValue =  0
//A线程任务执行完毕,解锁03-09 
16:40:29.393 17252-17303/? E/ReadWriteLockFragment: ThreadB start mCurrentValue =  0
//线程A解锁之后,线程B拿到锁,开始执行任务
03-09 16:40:31.395 17252-17303/? E/ReadWriteLockFragment: ThreadB end mCurrentValue =  1
//线程B执行任务完毕,解锁

3、代码示例:A读B读,B不阻塞

修改ThreadB代码

private class ThreadB extends Thread{
        @Override
        public void run() {
            super.run();
                readWriteLock.readLock().lock();//读锁
                Log.e(TAG, getClass().getSimpleName() + " start mCurrentValue =  " + mCurrentValue);
                try {
                    Thread.sleep(2000);//线程沉睡2秒
                }catch (Exception e){
                    e.printStackTrace();
                }
                Log.e(TAG,getClass().getSimpleName() + " end mCurrentValue =  " + mCurrentValue);
                readWriteLock.readLock().unlock();
        }
    }

再次运行,分析log

03-09 16:57:09.513 18709-18740/? E/ReadWriteLockFragment: ThreadA start mCurrentValue =  0 
//A线程启动,获取读锁成功,开始执行任务
03-09 16:57:09.516 18709-18741/? E/ReadWriteLockFragment: ThreadB start mCurrentValue =  0 
//B线程启动,也获取读锁成功,开始执行任务
03-09 16:57:11.516 18709-18740/? E/ReadWriteLockFragment: ThreadA end mCurrentValue =  0 
//A线程执行任务完毕,解锁
03-09 16:57:11.517 18709-18741/? E/ReadWriteLockFragment: ThreadB end mCurrentValue =  0 
//B线程执行任务完毕,解锁

从上面log时间信息可以看出,A线程与B线程并发执行,A读B读的时候,并不阻塞线程。

相关文章

网友评论

      本文标题:Java中线程同步(五):ReentrantReadWriteL

      本文链接:https://www.haomeiwen.com/subject/ziewgttx.html