Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock)
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
在学习Java的之前,你可能已经听说过读锁,写锁,读写锁,乐观锁,悲观锁。这些名词在学习数据库的时候几乎每个人都会有所了解的!当你学习java网络编程时,尤其是在处理多并发的情况时,你可能用过“synchronized”关键字是同步的方法,它可以用来同步代码块也可以用来同步方法。但JAVA中的锁并不是只有“synchronized”哟,在Java的并发库中你可能会进程看到一些可重入所(ReentrantLock)。
本篇博客就以重入读写锁(ReentrantReadWriteLock)来测试当两个线程的读锁和写锁是否可用同时访问。
一.两个线程同时上读锁的情况
1>.测试代码如下:
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.nio; 7 8 import java.util.concurrent.locks.ReentrantReadWriteLock; 9 10 /** 11 * 重入锁测试 12 */ 13 public class ReentrantLockDemo { 14 public static void main(String[] args) { 15 //通过并法库包的ReentrantReadWriteLock获取读写锁,里面既包含读锁也包含写锁。 16 final ReentrantReadWriteLock lock = new ReentrantReadWriteLock() ; 17 18 //开启2个线程,看他们谁先抢到线程谁就会先打印数据。最好是通过IDE的调试方法查看他们的执行过程。 19 new Thread(){ 20 public void run() { 21 //上读锁 22 lock.readLock().lock(); 23 System.out.println("xxx"); 24 //解读锁 25 lock.readLock().unlock(); 26 } 27 }.start(); 28 29 new Thread(){ 30 public void run() { 31 //上读锁 32 lock.readLock().lock(); 33 System.out.println("yyy"); 34 //上读锁 35 lock.readLock().unlock(); 36 } 37 }.start(); 38 } 39 }
2>.IDEA打断点注意事项
3>.运行Debug模式并进入第一个线程
4>.查看控制台输出信息
5>.运行线程2的代码
6>.查看线程2的控制台
7>.得出结论
答:在同一个程序中,一个线程拿到读锁且未释放锁时,另一个线程仍然可以继续使用读锁,他们之间并不互相影响!
二.两个线程一个上读锁,一个上写锁的情况
1>.测试代码
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.nio; 7 8 import java.util.concurrent.locks.ReentrantReadWriteLock; 9 10 /** 11 * 重入锁测试 12 */ 13 public class ReentrantLockDemo { 14 public static void main(String[] args) { 15 //通过并法库包的ReentrantReadWriteLock获取读写锁,里面既包含读锁也包含写锁。 16 final ReentrantReadWriteLock lock = new ReentrantReadWriteLock() ; 17 18 //开启2个线程,看他们谁先抢到线程谁就会先打印数据。最好是通过IDE的调试方法查看他们的执行过程。 19 new Thread(){ 20 public void run() { 21 //上读锁 22 lock.readLock().lock(); 23 System.out.println("xxx"); 24 //解读锁 25 lock.readLock().unlock(); 26 } 27 }.start(); 28 29 new Thread(){ 30 public void run() { 31 //上写锁 32 lock.writeLock().lock(); 33 System.out.println("yyy"); 34 //解写锁 35 lock.writeLock().unlock(); 36 } 37 }.start(); 38 } 39 }
2>.执行第一个线程
3>.查看控制端是有内容输出的
4>.切换到第二个线程执行代码
5>.得出结论
答:当一个线程拿到读锁时,另一个线程无法使用写锁!
三.两个线程一个上写锁,一个上读锁的情况
1>.测试代码
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.nio; 7 8 import java.util.concurrent.locks.ReentrantReadWriteLock; 9 10 /** 11 * 重入锁测试 12 */ 13 public class ReentrantLockDemo { 14 public static void main(String[] args) { 15 //通过并法库包的ReentrantReadWriteLock获取读写锁,里面既包含读锁也包含写锁。 16 final ReentrantReadWriteLock lock = new ReentrantReadWriteLock() ; 17 18 //开启2个线程,看他们谁先抢到线程谁就会先打印数据。最好是通过IDE的调试方法查看他们的执行过程。 19 new Thread(){ 20 public void run() { 21 //上读锁 22 lock.writeLock().lock(); 23 System.out.println("xxx"); 24 //解读锁 25 lock.writeLock().unlock(); 26 } 27 }.start(); 28 29 new Thread(){ 30 public void run() { 31 //上写锁 32 lock.readLock().lock(); 33 System.out.println("yyy"); 34 //解写锁 35 lock.readLock().unlock(); 36 } 37 }.start(); 38 } 39 }
2>.执行第一个线程
3>.查看第一个线程输出的内容
4>.执行第二线程
5>.得出结论
答:当一个线程拿到写锁时,另一个线程无法使用读锁!
四.两个线程同时上写锁的情况
1>.测试代码
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.nio; 7 8 import java.util.concurrent.locks.ReentrantReadWriteLock; 9 10 /** 11 * 重入锁测试 12 */ 13 public class ReentrantLockDemo { 14 public static void main(String[] args) { 15 //通过并法库包的ReentrantReadWriteLock获取读写锁,里面既包含读锁也包含写锁。 16 final ReentrantReadWriteLock lock = new ReentrantReadWriteLock() ; 17 18 //开启2个线程,看他们谁先抢到线程谁就会先打印数据。最好是通过IDE的调试方法查看他们的执行过程。 19 new Thread(){ 20 public void run() { 21 //上读锁 22 lock.writeLock().lock(); 23 System.out.println("xxx"); 24 //解读锁 25 lock.writeLock().unlock(); 26 } 27 }.start(); 28 29 new Thread(){ 30 public void run() { 31 //上写锁 32 lock.writeLock().lock(); 33 System.out.println("yyy"); 34 //解写锁 35 lock.writeLock().unlock(); 36 } 37 }.start(); 38 } 39 }
2>.执行第一个线程
3>.查看第一个线程输出的内容
4>.执行第二线程
5>.得出结论
答:当一个线程拿到写锁时,另一个线程无法使用写锁!