java可重入锁
2016-07-04 11:03
495 查看
目录
什么是可重入锁为什么要可重入
如何实现可重入锁
有不可重入锁吗
demo代码展示
参考文章
1
. 什么是可重入锁
锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当线程B尝试进入被这个锁保护的代码段的时候.就会被阻塞.而锁的操作粒度是”线程”,而不是调用(至于为什么要这样,下面解释).同一个线程再次进入同步代码的时候.可以使用自己已经获取到的锁,这就是可重入锁java里面内置锁(synchronize)和Lock(ReentrantLock)都是可重入的
2
. 为什么要可重入
如果线程A继续再次获得这个锁呢?比如一个方法是synchronized,递归调用自己,那么第一次已经获得了锁,第二次调用的时候还能进入吗? 直观上当然需要能进入.这就要求必须是可重入的.可重入锁又叫做递归锁,再举个例子.1 2 3 4 5 6 7 8 9 10 11 12 | public class Widget { public synchronized void doSomething() { ... } } public class LoggingWidget extends Widget { public synchronized void doSomething() { System.out.println(toString() + ": calling doSomething"); super.doSomething();//若内置锁是不可重入的,则发生死锁 } } |
3
. 如何实现可重入锁
为每个锁关联一个获取计数器和一个所有者线程,当计数值为0的时候,这个所就没有被任何线程只有.当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值置为1,如果同一个线程再次获取这个锁,技术值将递增,退出一次同步代码块,计算值递减,当计数值为0时,这个锁就被释放.ReentrantLock里面有实现
4
. 有不可重入锁吗
这个还真有.Linux下的pthread_mutex_t锁是默认是非递归的。可以通过设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t锁设置为递归锁。如果要自己实现不可重入锁,同可重入锁,这个计数器只能为1.或者0,再次进入的时候,发现已经是1了,就进行阻塞.jdk里面没有默认的实现类.
5
. demo代码展示
5.1 内置锁的可重入1 2 3 4 5 6 7 8 9 10 11 1213 | public class ReentrantTest { public void method1() { synchronized (ReentrantTest.class) { System.out.println("方法1获得ReentrantTest的内置锁运行了"); method2(); } } public void method2() { synchronized (ReentrantTest.class) { System.out.println("方法1里面调用的方法2重入内置锁,也正常运行了"); } } public static void main(String[] args) { new ReentrantTest().method1(); } } |
1 2 3 4 5 6 7 8 9 10 11 1213 | import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockTest { private Lock lock = new ReentrantLock(); public void method1() { lock.lock(); try { System.out.println("方法1获得ReentrantLock锁运行了"); method2(); } finally { lock.unlock(); } } public void method2() { lock.lock(); try { System.out.println("方法1里面调用的方法2重入ReentrantLock锁,也正常运行了"); } finally { lock.unlock(); } } public static void main(String[] args) { new ReentrantLockTest().method1(); } } |
1 2 3 4 5 6 7 8 9 10 11 1213 | import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReentrantTwoThreadTest { private static Lock lock = new ReentrantLock(); private static class T1 extends Thread { @Override public void run() { System.out.println("线程1启动"); lock.lock(); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } System.out.println("线程1终止"); } } private static class T2 extends Thread { @Override public void run() { System.out.println("线程2启动"); lock.lock(); lock.unlock(); System.out.println("线程2终止"); } } public static void main(String[] args) { new T1().start(); Thread.sleep(100); new T2().start(); } } |
6.
参考文章
可重入锁测试生产者消费者的一个更真实的例子
浅谈Java中的锁
java并发编程实战
相关文章推荐
- Java IO: System.in, System.out, System.err
- Java桥接模式(Bridge)-结构型
- AJAX编程技巧:在Struts Action中如何向客户端发送xml文件?
- myeclipse破解补丁激活失败方法
- springboot 使用心得
- Java IO:管道
- javaweb国际化
- 弄懂JDK、JRE和JVM到底是什么
- Java中的Connection赋值为null与conn.close
- 什么是Java位运算符
- java设计模式之策略模式
- struts
- JAVA设计模式之门面模式(外观模式)
- java设计模式
- StringUtils的常见方法
- java 用栈的原理(穷举)实现迷宫游戏
- Java基础——集合框架
- Java学习笔记之深入理解接口和抽象类
- Java 接口和抽象类的异同点
- (转)Java基础——嵌套类、内部类、匿名类