Java ConcurrentSkipListMap在某些线程中卡住
我有这个容器Java ConcurrentSkipListMap在某些线程中卡住,java,multithreading,concurrency,deadlock,Java,Multithreading,Concurrency,Deadlock,我有这个容器 private ConcurrentMap<Integer,SortedMap<Long,Object>> users; 有时它工作得很好,但有时(我想是在高负载情况下)某些用户进程方法(所有调用)会被卡住,永远不会输出第2节 如果我交换q.headMap(someNumber).clear()和q.put(obj.someId,obj) 它仍然没有输出第2节 我还尝试了LinkedBlockingQueue而不是ConcurrentSkipListMap
private ConcurrentMap<Integer,SortedMap<Long,Object>> users;
有时它工作得很好,但有时(我想是在高负载情况下)某些用户进程方法(所有调用)会被卡住,永远不会输出第2节
如果我交换q.headMap(someNumber).clear()代码>和q.put(obj.someId,obj)代码>
它仍然没有输出第2节
我还尝试了LinkedBlockingQueue
而不是ConcurrentSkipListMap
,但我也遇到了同样的问题
它看起来像一个死锁,但我没有在该结构上使用任何同步语句
请分享您的想法,如果您有一个可能有多个原因;最明显的是不同步的代码。执行线程转储以轻松确定原因
一些问题:
在ConcurrentSkipListMap
JavaDocs中,它在headMap()
因此,如果obj.someId.compareTo(someNumber)<0
您可以在put()
处得到一个IllegalArgumentException
,它在任何地方都不会被处理
这也会导致比赛条件:
q.headMap( someNumber ).clear();
q.put( obj.someId, obj )
如果两个线程具有(thread1)someNumber=(thread2)obj.someId
,您将得到一个争用条件,谁知道下面会发生什么。此外,正如JavaDocs所说,clear()
不是一个原子操作
您没有提到您使用用户
引用对象的另一个地方;用户是如何填充的。问题不在于代码被卡住,而在于它抛出异常,异常由ADPool无声处理。我试图通过启用日志功能来推动定制ThreadFactory,但它仍然不起作用。解决方案是为运行时异常提供适当的尝试捕获
所以我学到的教训是,如果您的部分代码没有在线程池中执行,可能是因为RuntimeException,您应该提供更多的try Catch来查找原因听起来是个愚蠢的想法,但是,您确定您的logger实例是线程安全的吗?可能是记录器实际导致(潜在)死锁吗?尝试将每个日志语句放在同步块中,只是为了调试,看看问题是否消失。它是log4j2。我将尝试发布更新的log4j2。第1部分总是得到输出,并且在“q”上操作后总是会卡住,所以我认为这不是问题,但我会尽力谢谢你,谢谢你,但我没有得到任何异常,所以我们必须假设某个数字是正确的。竞态条件会导致线程安全操作中的死锁吗?@MySqlError不看内部很难说。虽然clear()
不是原子的说法刚刚在我身上引起了一个启示(我必须亲自检查javadoc)。特别是对于SkipListMap,可能有线程试图在半清除的映射上执行put操作,从而导致数据损坏(或可能的死锁)。但是,您确实说过您尝试了一个LinkedBlockingQueue
,它确实具有原子清除功能,这表明您的问题可能在其他地方(如果您选择使用SkipListMap,您仍然需要修复竞态条件)。@MySqlError但是您如何知道您有死锁?你有没有接受线程转储?回答您的问题:我不这么认为(我相信JDK类构建得足够好,不会死锁,但这取决于内部实现)。还有,您如何确定没有异常?它不会出现在日志中,除非你得到Future
treat它(你的代码没有)。请参阅此处了解更多详细信息-您是对的,它不应该是死锁,因为如果它是死锁,那么它应该使整个线程池死锁,在我的示例中,该线程池只有8个线程。所以,如果运行时异常发生在线程池中,它将是静默的?如果是这样,我想这可能是我正在处理的一个问题
executorService.execute(new Runnable() {
@Override
public void run() {
process(obj);
}
});
The returned map will throw an IllegalArgumentException on an attempt to insert a key outside its range.
q.headMap( someNumber ).clear();
q.put( obj.someId, obj )