锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当线程B尝试进入被这个锁保护的代码段的时候.就会被阻塞.而锁的操做粒度是”线程”,而不是调用(至于为何要这样,下面解释).同一个线程再次进入同步代码的时候.可使用本身已经获取到的锁,这就是可重入锁
java里面内置锁(synchronize)和Lock(ReentrantLock)都是可重入的html
若是线程A继续再次得到这个锁呢?好比一个方法是synchronized,递归调用本身,那么第一次已经得到了锁,第二次调用的时候还能进入吗? 直观上固然须要能进入.这就要求必须是可重入的.可重入锁又叫作递归锁,再举个例子.java
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();//若内置锁是不可重入的,则发生死锁 } } |
这个例子是java并发编程实战中的例 子.synchronized 是父类Widget的内置锁,当执行子 类的方法的时候,先获取了一次Widget的锁,而后在执行super的时候,就要获取一次,若是不可重入,那么就跪了.git
为每一个锁关联一个获取计数器和一个全部者线程,当计数值为0的时候,这个所就没有被任何线程只有.当线程请求一个未被持有的锁时,JVM将记下锁的持有者,而且将获取计数值置为1,若是同一个线程再次获取这个锁,技术值将递增,退出一次同步代码块,计算值递减,当计数值为0时,这个锁就被释放.
ReentrantLock里面有实现github
这个还真有.Linux下的pthread_mutex_t锁是默认是非递归的。能够经过设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t锁设置为递归锁。若是要本身实现不可重入锁,同可重入锁,这个计数器只能为1.或者0,再次进入的时候,发现已是1了,就进行阻塞.jdk里面没有默认的实现类.编程
5.1 内置锁的可重入并发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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(); } } |
5.2 lock对象的可重入ide
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
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(); } } |
5.3 不一样线程不可访问同一锁post
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
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("线程2终止"); } } 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(); } } |