在本地资源上同步时Java死锁?
我看到同一行代码中多个线程死锁的问题.
我不能在本地或任何测试中重现问题,但是生产中的线程转储已经非常清楚地显示了问题. 我无法理解为什么线程会在下面的同步线上被阻塞,因为在调用堆栈或任何其他线程中的Object上没有其他同步.有没有人知道发生了什么,或者我怎么能重现这个问题(目前尝试15个线程都在循环中击中trim(),同时通过我的队列处理2000个任务 – 但无法重现) 在下面的线程转储中,我认为具有“锁定”状态的多个线程可能是Java Bug:http://bugs.java.com/view_bug.do?bug_id=8047816的一种表现形式,其中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) 这是提取的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); } } } } } 解决方法
从
documentation for
HashMap
(强调他们的) 您正在以不同步的方式读取和写入地图. 我认为没有理由认为您的代码是线程安全的. 我建议你由于缺乏线程安全而导致无限循环. 输入同步块相对较慢,因此线程转储可能总是至少显示等待获取锁的几个线程. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Java通过JDBC操作ORACLE数据库工具类
- 如何使用PDFBox对动态创建的PDF文档进行数字签名?
- 是否有JFoodies FormLayout和DefaultFormBuilder的JavaFX等
- java – django-like框架?
- 关于Java static的常见问题和使用误区
- Java:如果不知道如何初始化数组大小?
- java – 将图像从Android设备发送到服务器进行处理并将结果
- java – 在Linux上使用Bundle-NativeCode不起作用
- VHDL std_logic_vector索引与“downto”
- 让你一看就明白什么是单列模式(和静态静态工厂模式)--java版