最近在读<<Java并发编程实践>>,在第二章中线程安全中降到线程锁的重进入(Reentrancy)
当一个线程请求其它的线程已经占有的锁时,请求线程将被阻塞。然而内部锁是可重进入的,因此线程在试图获得它自己占用的锁是,请求会成功。重进入意味着请求是基于“每一个线程”,而不是基于“每一次调用”(互斥锁是基于每次调用的)。重进入的实现是通过为每一个锁关联一个请求技术器和一个占有他的线程。当计数为0时,认为锁是未被占用的。线程请求一个未被占有的锁时候,JVM将记录锁的占有者,并且将请求计数设置为1。如果同一个线程再次请求这个锁,计数将递增;每次占用线程退出语句块时,计数器值将递减,直到计数器达到0时候,锁被释放。
重进入方便了锁行为的封装,因此简化了面向对象并发代码的开发。
public class Widget {
public synchronized void doSomething() {
...
}
}
public class LoggingWidget extends Widget {
public synchronized void doSomething() {
System.out.println(toString() + ": calling doSomething");
super.doSomething();//若内置锁是不可重入的,则发生死锁
}
}
在例子中,子类覆盖了父类的synchronized 类型的方法,并调用父类中的方法。如果没有可重入的锁,子类中可能就会产生死锁,因为Widget和LoggingWidget中的dosomething方法都是synchronized 类型的,都会在处理前试图获得Widget的锁。倘若内部锁不是可重入的,super.doSomething的调用者就永远无法获得Widget的锁。因为锁已经被占用,导致线程永久的延迟,等待着一个永远无法获得的锁。
以java上代码在同一个线程执行时,不会导致死锁,java中的synchronized 本身就是可以重入的(reentrant), 不管是synchronized方法,还是synchronized statements。参见:
http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
http://stackoverflow.com/questions/5787957/reentrant-synchronization-behavior-with-synchronized-statements
下面部分摘自论坛:
1、LoggingWidget 的对象调用doSomething方法时,锁对象为LoggingWidget对象 super.doSomething()调用是锁对象是LoggingWidget对象 运行程序,查看thread dump发现:调用super.doSomething()时锁对象依然是LoggingWidget对象。
"线程#1" prio=6 tid=0x0bd60400 nid=0x16f8 waiting on condition [0x0bf8f000..0x0bf8fd68]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at Widget.doSomething(Widget.java:4)
- locked <0x03fbc150> (a LoggingWidget)
at LoggingWidget.doSomething(LoggingWidget.java:5)
- locked <0x03fbc150> (a LoggingWidget)
at LoggingWidget$1.run(LoggingWidget.java:15)
Locked ownable synchronizers:
- None
cectsky回复:
super.doSomething();子类会去get Widget的monitorlock,此时就会取到lock,如果monitorlock不可重入,就需要再次拿LoggingWidget的lock,but,此时LoggingWidget的lock已经被占用了,所以会发生deadlock。
支持可重入的话,只是简单的实现进入计数,每次进入+1,退出-1,如果计数器为0,则认为此时对象是没有被加锁 。
因为JVM的可重入解决了这个问题啊,所以dump里看到的是正确的流程。
2、在网上搜索发现,大伙都如是说:
分享到:
相关推荐
- **ReentrantLock**:是Java并发包`java.util.concurrent.locks`中的可重入锁,提供了比`synchronized`更细粒度的控制,支持公平锁和非公平锁,以及可中断和可定时的获取锁。 7. **TestSynchronized 示例** 通常...
Java 中的 Lock 和 Synchronized 的区别 Java 语言中有很多相似关键字或相似意义的字,...lock 提供了更加灵活和高效的锁机制,可以满足不同场景下的需求,而 synchronized 则是 Java 中的关键字,具有语言的内置性。
Java作为一种广泛使用的编程语言,其提供了内置的同步机制来实现锁的功能,其中"Synchronized"关键字是最为常用的方式之一。在Java高并发编程领域,理解Synchronized锁的升级机制是非常重要的。 首先需要知道的是,...
深入理解Java内置锁(synchronized)和显式锁(ReentrantLock) Java中有两种锁机制:内置锁(synchronized)和显式锁(ReentrantLock)。内置锁是Java语言提供的一种同步机制,使用synchronized关键字声明的方法或...
在Java多线程高并发编程中,重入锁(ReentrantLock)是一个至关重要的概念,它提供了比Java内置锁(synchronized)更细粒度的控制,并且具有更高的可读性和可扩展性。本篇文章将深入探讨重入锁的相关知识点。 首先...
相比之下,ReentrantLock(可重入锁)是Java并发包java.util.concurrent.locks中的一个类,提供了更细粒度的锁控制。ReentrantLock允许显式获取和释放锁,并且支持更丰富的锁原语,如公平锁、非公平锁、可中断锁、...
每个Java对象都可以作为锁,`synchronized`关键字实际上是在获取和释放对象的监视器锁(也称为内置锁或互斥锁)。对于非静态方法,锁是当前对象;对于静态方法,锁是对应的类的Class对象。 三、synchronized的两种...
2. ReentrantLock(可重入锁):实现了Lock接口,是Java中唯一可重入的互斥锁,与内置锁有类似的语义,但功能更强大。 ```java import java.util.concurrent.locks.Lock; import java.util.concurrent.locks....
标题和描述概述的知识点主要集中在Java的多线程机制中,特别是`wait`和`notify`方法在同步锁中的应用。这些方法对于控制线程之间的交互至关重要,尤其是在资源有限或需要确保数据一致性的情况下。 ### Java同步锁...
总结来说,Java多线程中的内置锁和显式锁各有优劣。内置锁简洁易用,但控制有限;显式锁提供了更多灵活性,但使用起来相对复杂。根据具体应用场景选择合适的锁机制,能有效提高并发程序的性能和可维护性。
- `synchronized`关键字与Java内存模型(JMM)紧密关联,确保了可见性和有序性,防止数据竞争。 总之,`synchronized`关键字是Java中实现线程同步的关键,它通过锁机制保证了共享资源的线程安全访问,防止并发问题...
2. **可重入性**:synchronized也支持可重入,即一个线程已经获得了锁,可以再次进入持有该锁的代码块,这对于递归调用是必要的。 3. **内存可见性**:synchronized能确保线程之间的内存可见性,即当一个线程修改了...
ReentrantLock,即可重入锁,是Java 5引入的锁实现,它在功能上与synchronized相似,但提供了更多高级特性。通过调用lock()和unlock()方法,程序员可以更精确地控制锁的获取和释放。ReentrantLock的一个关键特性是可...
在Java中,内置锁是通过synchronized关键字实现的,而显示锁则是通过java.util.concurrent.locks包中的接口和类实现的。显示锁的一个重要接口是Lock,它提供了对锁操作的更细粒度控制,而ReentrantLock是Lock的一个...
在Java多线程编程中,锁机制是保证线程安全和数据一致性的重要工具。本篇文章将深入探讨Java锁的释放与建立,以及它们之间的_happens-before_关系,旨在帮助开发者更好地理解和应用并发控制。 首先,Java中的锁主要...
总结,`synchronized`是Java中实现线程同步的重要机制,它的核心在于监视器锁和互斥性。理解和合理使用`synchronized`能够帮助我们构建稳定、高效的多线程程序,但同时也要注意避免潜在的死锁和性能问题。在实际编程...
- **ReentrantLock**:可重入锁,与synchronized具有相似的特性,但提供了更多的灵活性,如尝试获取锁、可中断的等待和公平锁等。 - **ReadWriteLock**:读写锁,允许多个读取线程同时访问,但写入操作是独占的,...
`synchronized`关键字是Java中的内置锁机制,它基于Java内存模型(JMM)来确保线程间的可见性和有序性。当一个线程持有对象的锁时,其他线程试图访问该对象的同步代码会阻塞,直到锁被释放。 4. **Java锁的类型**...
无论是内置的 `synchronized` 还是 `java.util.concurrent.locks.ReentrantLock`,都通过可重入性确保了在复杂多线程环境下的正确性和可靠性。在实际编程中,理解并熟练掌握可重入锁的原理和使用方法,对优化并发...