可重入概念:
一个线程去请求其他线程所持有的锁时,发出请求的线程就会发生阻塞。
如果一个线程试图去请求一个已经由他自己持有的锁的时,并且该锁是可重入的,则请求就会成功。
重入意味着获取锁的粒度是线程,而不是调用。重入避免了一些死锁情况的发生。
java的可重入锁:
synchronized:可重入锁;
java.util.concurrent.locks.ReentrantLock:可重入锁;
可重入锁的一种实现方式:
每个锁关联一个计数器和一个持有者对象。计数器为0,则该锁没有被持有。
如果某个线程请求一个空闲锁,则jvm记录锁的持有者,并且将计数器置为1。
该线程再次请求获得该锁时,计数器加一。
当线程释放一次锁,计数器减一,直到计数器为0,则最终释放锁。
可重入锁的两种使用例子:
例子1:
public class Example {
public synchronized void lock1() {
System.out.println("进入lock1");
}
public synchronized void lock2() {
System.out.println("进入lock2");
lock1();
}
public static void main(String[] args) {
new Example().lock2();
}
}
例子2:
public class Widget {
public synchronized void dosomething() {
System.out.println("widget do something");
}
}
public class LoggerWidget extends Widget {
public synchronized void dosomething() {
System.out.println("LoggerWidget do something");
super.dosomething();
}
public static void main(String[] args) {
new LoggerWidget().dosomething();
}
}
例子1说明:
例子1很好理解,同一个实例的两个方法,可重入显然获得的是同一个对象。
例子2说明:
该例子可能会有疑惑。
当线程调用LoggerWidget的dosomething方法的时候,取得LoggerWidget对象锁。
方法中调用super.dosomething方法,调用者依然是当前对象,即LoggerWidget对象。因此进入
super.dosomething方法获得锁依然是LoggerWidget对象锁,这里体现了锁的可重入性。
总结:
对于java锁来说,锁的持有者是线程,锁本身可以认为是对象。








网友评论