在本地资源上进行同步时发生Java死锁?
我发现在同一行代码中有多个线程死锁的问题。 我无法在本地或任何测试中重现该问题,但生产中的线程转储已经非常清楚地显示了该问题 我不明白为什么线程会在下面的synchronized行中被阻塞,因为在调用堆栈或任何其他线程中的对象上没有其他同步。有没有人知道发生了什么,或者我如何重现这个问题(目前正在尝试使用15个线程在一个循环中全部命中trim(),同时通过我的队列处理2000个任务,但无法重现) 在下面的线程转储中,我认为具有“锁定”状态的多个线程可能是Java Bug的一种表现:JStack报告处于错误状态的线程。 (我使用的是JDK版本:1.7.0_51) 干杯 这里是线程转储中线程的视图在本地资源上进行同步时发生Java死锁?,java,multithreading,concurrency,thread-safety,deadlock,Java,Multithreading,Concurrency,Thread Safety,Deadlock,我发现在同一行代码中有多个线程死锁的问题。 我无法在本地或任何测试中重现该问题,但生产中的线程转储已经非常清楚地显示了该问题 我不明白为什么线程会在下面的synchronized行中被阻塞,因为在调用堆栈或任何其他线程中的对象上没有其他同步。有没有人知道发生了什么,或者我如何重现这个问题(目前正在尝试使用15个线程在一个循环中全部命中trim(),同时通过我的队列处理2000个任务,但无法重现) 在下面的线程转储中,我认为具有“锁定”状态的多个线程可能是Java Bug的一种表现:JStack报
"xxx>Job Read-3" daemon prio=10 tid=0x00002aca001a6800 nid=0x6a3b waiting for monitor entry [0x0000000052ec4000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.mycompany.collections.CustomQueue.remove(CustomQueue.java:101)
- locked <0x00002aae6465a650> (a java.util.ArrayDeque)
at com.mycompany.collections.CustomQueue.trim(CustomQueue.java:318)
at com.mycompany.collections.CustomQueue.itemProcessed(CustomQueue.java:302)
at com.mycompany.collections.CustomQueue.trackCompleted(CustomQueue.java:147)
at java.util.concurrent.ThreadPoolExecutor.afterExecute(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- <0x00002aaf5f9c2680> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"xxx>Job Read-2" daemon prio=10 tid=0x00002aca001a5000 nid=0x6a3a waiting for monitor entry [0x0000000052d83000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.mycompany.collections.CustomQueue.remove(CustomQueue.java:101)
- locked <0x00002aae6465a650> (a java.util.ArrayDeque)
at com.mycompany.collections.CustomQueue.trim(CustomQueue.java:318)
at com.mycompany.collections.CustomQueue.itemProcessed(CustomQueue.java:302)
at com.mycompany.collections.CustomQueue.trackCompleted(CustomQueue.java:147)
at java.util.concurrent.ThreadPoolExecutor.afterExecute(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- <0x00002aaf5f9ed518> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"xxx>Job Read-1" daemon prio=10 tid=0x00002aca00183000 nid=0x6a39 waiting for monitor entry [0x0000000052c42000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.mycompany.collections.CustomQueue.remove(CustomQueue.java:101)
- waiting to lock <0x00002aae6465a650> (a java.util.ArrayDeque)
at com.mycompany.collections.CustomQueue.trim(CustomQueue.java:318)
at com.mycompany.collections.CustomQueue.itemProcessed(CustomQueue.java:302)
at com.mycompany.collections.CustomQueue.trackCompleted(CustomQueue.java:147)
at java.util.concurrent.ThreadPoolExecutor.afterExecute(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- <0x00002aaf5f9ecde8> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"xxx>Job Read-0" daemon prio=10 tid=0x0000000006a83000 nid=0x6a36 waiting for monitor entry [0x000000005287f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.mycompany.collections.CustomQueue.remove(CustomQueue.java:101)
- waiting to lock <0x00002aae6465a650> (a java.util.ArrayDeque)
at com.mycompany.collections.CustomQueue.trim(CustomQueue.java:318)
at com.mycompany.collections.CustomQueue.itemProcessed(CustomQueue.java:302)
at com.mycompany.collections.CustomQueue.trackCompleted(CustomQueue.java:147)
at java.util.concurrent.ThreadPoolExecutor.afterExecute(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
“xxx>作业读取-3”守护进程prio=10 tid=0x00002aca001a6800 nid=0x6a3b等待监视器条目[0x0000000052ec4000]
java.lang.Thread.State:阻塞(在对象监视器上)
在com.mycompany.collections.CustomQueue.remove(CustomQueue.java:101)上
-锁定(一个java.util.ArrayDeque)
位于com.mycompany.collections.CustomQueue.trim(CustomQueue.java:318)
位于com.mycompany.collections.CustomQueue.itemProcessed(CustomQueue.java:302)
在com.mycompany.collections.CustomQueue.trackCompleted上(CustomQueue.java:147)
位于java.util.concurrent.ThreadPoolExecutor.afterExecute(未知源)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(未知源)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(未知源)
位于java.lang.Thread.run(未知源)
锁定可拥有的同步器:
-(一个java.util.concurrent.ThreadPoolExecutor$Worker)
“xxx>Job Read-2”守护进程prio=10 tid=0x00002aca001a5000 nid=0x6a3a等待监视器条目[0x0000000052d83000]
java.lang.Thread.State:阻塞(在对象监视器上)
在com.mycompany.collections.CustomQueue.remove(CustomQueue.java:101)上
-锁定(一个java.util.ArrayDeque)
位于com.mycompany.collections.CustomQueue.trim(CustomQueue.java:318)
位于com.mycompany.collections.CustomQueue.itemProcessed(CustomQueue.java:302)
在com.mycompany.collections.CustomQueue.trackCompleted上(CustomQueue.java:147)
位于java.util.concurrent.ThreadPoolExecutor.afterExecute(未知源)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(未知源)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(未知源)
位于java.lang.Thread.run(未知源)
锁定可拥有的同步器:
-(一个java.util.concurrent.ThreadPoolExecutor$Worker)
“xxx>Job Read-1”守护进程prio=10 tid=0x00002aca00183000 nid=0x6a39等待监视器条目[0x0000000052c42000]
java.lang.Thread.State:阻塞(在对象监视器上)
在com.mycompany.collections.CustomQueue.remove(CustomQueue.java:101)上
-等待锁定(一个java.util.ArrayDeque)
位于com.mycompany.collections.CustomQueue.trim(CustomQueue.java:318)
位于com.mycompany.collections.CustomQueue.itemProcessed(CustomQueue.java:302)
在com.mycompany.collections.CustomQueue.trackCompleted上(CustomQueue.java:147)
位于java.util.concurrent.ThreadPoolExecutor.afterExecute(未知源)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(未知源)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(未知源)
位于java.lang.Thread.run(未知源)
锁定可拥有的同步器:
-(一个java.util.concurrent.ThreadPoolExecutor$Worker)
“xxx>Job Read-0”守护进程prio=10 tid=0x0000000006a83000 nid=0x6a36等待监视器条目[0x000000005287f000]
java.lang.Thread.State:阻塞(在对象监视器上)
在com.mycompany.collections.CustomQueue.remove(CustomQueue.java:101)上
-等待锁定(一个java.util.ArrayDeque)
位于com.mycompany.collections.CustomQueue.trim(CustomQueue.java:318)
位于com.mycompany.collections.CustomQueue.itemProcessed(CustomQueue.java:302)
在com.mycompany.collections.CustomQueue.trackCompleted上(CustomQueue.java:147)
位于java.util.concurrent.ThreadPoolExecutor.afterExecute(未知源)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(未知源)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(未知源)
位于java.lang.Thread.run(未知源)
这里是提取的Java代码,它显示了错误所在
public class Deadlock {
final Deque<Object> delegate = new ArrayDeque<>();
final long maxSize = Long.MAX_VALUE;
private final AtomicLong totalExec = new AtomicLong();
private final Map<Object, AtomicLong> totals = new HashMap<>();
private final Map<Object, Deque<Long>> execTimes = new HashMap<>();
public void trim() {
//Possible optimization is evicting in chunks, segmenting by arrival time
while (this.totalExec.longValue() > this.maxSize) {
final Object t = this.delegate.peek();
final Deque<Long> execTime = this.execTimes.get(t);
final Long exec = execTime.peek();
if (exec != null && this.totalExec.longValue() - exec > this.maxSize) {
//If Job Started Inside of Window, remove and re-loop
remove();
}
else {
//Otherwise exit the loop
break;
}
}
}
public Object remove() {
Object removed;
synchronized (this.delegate) { //4 Threads deadlocking on this line !
removed = this.delegate.pollFirst();
}
if (removed != null) {
itemRemoved(removed);
}
return removed;
}
public void itemRemoved(final Object t) {
//Decrement Total & Queue
final AtomicLong catTotal = this.totals.get(t);
if (catTotal != null) {
if (!this.execTimes.get(t).isEmpty()) {
final Long exec = this.execTimes.get(t).pollFirst();
if (exec != null) {
catTotal.addAndGet(-exec);
this.totalExec.addAndGet(-exec);
}
}
}
}
}
公共类死锁{
最终Deque委托=新ArrayQue();
最终长最大尺寸=长最大值;
private final AtomicLong totalExec=新的AtomicLong();
私有最终映射总计=新HashMap();
private final Map execTimes=new HashMap();
公共空间修剪(){
//可能的优化是逐块逐出,按到达时间分段
而(this.totalExec.longValue()>this.maxSize){
final Object t=this.delegate.peek();
final Deque execTime=this.execTimes.get(t);
final Long exec=execTime.peek();
if(exec!=null&&this.totalExec.longValue()-exec>this.maxSize){
//如果作业在窗口内启动,请删除并重新循环
删除();
}
否则{
//否则退出循环
打破
}
}
}
公共对象删除(){
移除物体;
已同步(this.delegate){//4个线程在这一行死锁!
removed=this.delegate.pollFirst();
}
如果(已删除!=null){
项目移除(移除);
}
移除返回;
}
删除公共无效项(最终对象t){
//减量总计和队列
最终原子长度catTotal=this.totals.get(t);
if(catTotal!=null){
如果(!
"xxx>Job Read-3" daemon prio=10 tid=0x00002aca001a6800 nid=0x6a3b waiting for monitor entry [0x0000000052ec4000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.mycompany.collections.CustomQueue.remove(CustomQueue.java:101)
- locked <0x00002aae6465a650> (a java.util.ArrayDeque)
at com.mycompany.collections.CustomQueue.trim(CustomQueue.java:318)