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读的时候,并不阻塞线程。
网友评论