问题是围绕“多个 Java 线程看似锁定同一个监视器”的讨论。在我们的应用程序中,我们面临着类似的问题。有时应用程序运行非常缓慢。已捕获多个线程转储。线程转储表明有 2/3 个线程在同一时间点获取了相同的锁对象并处于 BLOCKED 状态。其他线程(在不同时间点有 10 到 20 个)在等待同一个锁对象时被阻塞。伪线程转储如下所示:
"MyThread-91" prio=3 tid=0x07552800 nid=0xc7 waiting for monitor entry [0xc4dff000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.myCompany.abc.util.MySharedLinkedList$MySharedIterator.hasNext(MySharedLinkedList.java:177)
- locked <0xce1fb810> (a com.myCompany.abc.util.MySharedLinkedList)
at com.myCompany.abc.util.MyEventProcessor.notifyListeners(MyEventProcessor.java:2644)
...............................................................................................
"MyThread-2" prio=3 tid=0x07146400 nid=0x6e waiting for monitor entry [0xc6aef000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.myCompany.abc.util.MySharedLinkedList$MySharedIterator.hasNext(MySharedLinkedList.java:177)
- locked <0xce1fb810> (a com.myCompany.abc.util.MySharedLinkedList)
at com.myCompany.abc.util.MyEventProcessor.notifyListeners(MyEventProcessor.java:2644)
................................................................................................
"MyThread-14" prio=3 tid=0x074b9400 nid=0x7a waiting for monitor entry [0xc64ef000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.myCompany.abc.util.MySharedLinkedList$MySharedIterator.next(MySharedLinkedList.java:194)
- waiting to lock <0xce1fb810> (a com.myCompany.abc.util.MySharedLinkedList)
at com.myCompany.abc.util.MyEventProcessor.notifyListeners(MyEventProcessor.java:2646)
................................................................................................
MyThread-91 和 MyThread-2 在锁定 <0xce1fb810> 时被阻塞。MyThread-14 在等待同一个锁 <0xce1fb810> 时处于阻塞状态。
我们肯定不会在这里遇到任何线程死锁问题。请注意,在任何时间点被锁 (0xce1fb810) 阻塞的线程随后都会释放它。但是,其他一些线程在获取相同的锁对象后会被阻塞。根据上面提到的讨论(&格雷提供的示例代码),这可能是因为在同步块中调用了 wait()。但是,我们检查了我们的代码,我们没有看到在同步块中调用了任何 wait()。在我们的例子中,它是链表的内部实现,而链表又具有实现迭代器的内部类。迭代器实现的next()和hasNext()锁在同一个外部类的实例上,即自定义链表的实例上。当多个线程调用 next() 和 hasNext() 时,它们在“获取”同一个锁后进入 BLOCKED 状态。
这是伪代码:
public final class MySharedLinkedList<E> implements Collection<E> {
/**
* Represents an entry in the list.
*/
private static final class Entry<E> {
//Instance variables and methods for Entry goes here.
}
/**
* Non fail-fast implementation of iterator for this list.
*/
public final class MySharedIterator implements Iterator<E> {
public boolean hasNext() {
//Some code goes here.
synchronized (MySharedLinkedList.this) {
//Some code goes here.
}
}
public E next() {
//Some code goes here.
synchronized (MySharedLinkedList.this) {
//Some code goes here.
}
}
}
public synchronized Iterator<E> iterator() {
//Returns a new instance of the iterator.
}
}
/**
* Singleton Instance
*/
public class MyEventProcessor {
//listeners contains a number of Node objects
private final SharedLinkedList<Node> listeners = new SharedLinkedList<Node>();
private void notifyListeners() {
final SharedLinkedList<ProvAPIEventNode>.SharedIterator iterator = listeners.sharedIterator();
try {
while (iterator.hasNext()) {
final Node node = iterator.next();
//Lots of other things go here
} catch (Exception e) {
//Handle the exception
}
}
}
}
所以,问题是还有什么(除了wait())可能导致这种情况?
此博客讨论了类似的情况(在“示例 2:当处理性能异常缓慢时”部分下)。但不确定这里是否发生了类似的事情。
不要将此线程作为this或this的副本关闭。如前所述,行为相似,但我想根本原因可能不是。
想法??