Java:线程在没有获取锁的情况下持有锁

Posted

技术标签:

【中文标题】Java:线程在没有获取锁的情况下持有锁【英文标题】:Java: Thread holds lock without having aquired it 【发布时间】:2013-10-28 21:17:43 【问题描述】:

我最近遇到了一个非常奇怪的状态的多线程死锁。当一个线程实际上从未在其堆栈跟踪的任何方法中请求锁时,它似乎持有一个锁。这是必要的堆栈跟踪:

Found one Java-level deadlock:
=============================
"pool-1-thread-2":
  waiting to lock monitor 0x000000000751fc20 (object 0x00000000f55e2960, a de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager$ExtensionLoader),
  which is held by "pool-1-thread-1"
"pool-1-thread-1":
  waiting to lock monitor 0x000000000052ba78 (object 0x00000000f55dfc98, a de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager),
  which is held by "pool-1-thread-2"

Java stack information for the threads listed above:
===================================================
"pool-1-thread-2":
    at java.lang.ClassLoader.checkCerts(ClassLoader.java:782)
    - waiting to lock <0x00000000f55e2960> (a de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager$ExtensionLoader)
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:487)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:625)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager$ExtensionLoader.loadClassDirect(CraftElevatorsExtensionManager.java:149)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager$ExtensionLoader.access$4(CraftElevatorsExtensionManager.java:147)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager.findClass(CraftElevatorsExtensionManager.java:85)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    - locked <0x00000000f55dfc98> (a de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:295)
    - locked <0x00000000f55dfc38> (a de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager$ExtensionLoader)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager$ExtensionLoader.loadClass(CraftElevatorsExtensionManager.java:231)
    - locked <0x00000000f55dfc98> (a de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2436)
    at java.lang.Class.privateGetPublicMethods(Class.java:2556)
    at java.lang.Class.getMethods(Class.java:1412)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.elevator.CraftElevatorEventManager.register(CraftElevatorEventManager.java:147)
    at de.ntcomputer.minecraft.elevators2.doorsext.implementation.elevator.CraftElevatorDoorsExtension.onEnable(CraftElevatorDoorsExtension.java:61)
    - locked <0x00000000f55b8e58> (a de.ntcomputer.minecraft.elevators2.doorsext.implementation.elevator.CraftElevatorDoorsExtension)
    at de.ntcomputer.minecraft.elevators2.plugin.api.elevator.extension.CraftElevatorExtension.initialize(CraftElevatorExtension.java:16)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.elevator.CraftElevator.initialize(CraftElevator.java:72)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storage.CraftElevatorLoader.loadSync(CraftElevatorLoader.java:48)
    - locked <0x00000000f55b8f08> (a de.ntcomputer.minecraft.elevators2.plugin.implementation.storage.CraftElevatorLoader)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storage.CraftElevatorLoader.access$0(CraftElevatorLoader.java:39)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storage.CraftElevatorLoader$1.run(CraftElevatorLoader.java:64)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.scheduler.CraftElevatorTask.run(CraftElevatorTask.java:53)
    at org.bukkit.craftbukkit.v1_6_R3.scheduler.CraftTask.run(CraftTask.java:53)
    at org.bukkit.craftbukkit.v1_6_R3.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
"pool-1-thread-1":
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager$ExtensionLoader.loadClass(CraftElevatorsExtensionManager.java:231)
    - waiting to lock <0x00000000f55dfc98> (a de.ntcomputer.minecraft.elevators2.plugin.implementation.extension.CraftElevatorsExtensionManager)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at de.ntcomputer.minecraft.elevators2.extfloors.implementation.elevator.CraftInteractiveElevatorFloorsExtension.deserializeFloor(CraftInteractiveElevatorFloorsExtension.java:116)
    at de.ntcomputer.minecraft.elevators2.extfloors.implementation.elevator.CraftElevatorFloorsExtension$2.deserialize(CraftElevatorFloorsExtension.java:84)
    at de.ntcomputer.minecraft.elevators2.extfloors.implementation.elevator.CraftElevatorFloorsExtension$2.deserialize(CraftElevatorFloorsExtension.java:1)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storagefile.CraftStorageSectionReader.deserializeObject(CraftStorageSectionReader.java:151)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storagefile.CraftStorageSectionReader.deserializeCoreObject(CraftStorageSectionReader.java:199)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storagefile.CraftStorageSectionReader.inflateKeyMapEmpty(CraftStorageSectionReader.java:530)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storagefile.CraftStorageSectionReader.inflateMapValuesEmpty(CraftStorageSectionReader.java:996)
    at de.ntcomputer.minecraft.elevators2.extfloors.implementation.elevator.CraftElevatorFloorsExtension.onEnable(CraftElevatorFloorsExtension.java:76)
    at de.ntcomputer.minecraft.elevators2.extfloors.implementation.elevator.CraftInteractiveElevatorFloorsExtension.onEnable(CraftInteractiveElevatorFloorsExtension.java:70)
    at de.ntcomputer.minecraft.elevators2.plugin.api.elevator.extension.CraftElevatorExtension.initialize(CraftElevatorExtension.java:16)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.elevator.CraftElevator.initialize(CraftElevator.java:72)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storage.CraftElevatorLoader.loadSync(CraftElevatorLoader.java:48)
    - locked <0x00000000f5601ac8> (a de.ntcomputer.minecraft.elevators2.plugin.implementation.storage.CraftElevatorLoader)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storage.CraftElevatorLoader.access$0(CraftElevatorLoader.java:39)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.storage.CraftElevatorLoader$1.run(CraftElevatorLoader.java:64)
    at de.ntcomputer.minecraft.elevators2.plugin.implementation.scheduler.CraftElevatorTask.run(CraftElevatorTask.java:53)
    at org.bukkit.craftbukkit.v1_6_R3.scheduler.CraftTask.run(CraftTask.java:53)
    at org.bukkit.craftbukkit.v1_6_R3.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)

Found 1 deadlock.

如您所见,线程 2 尝试锁定显然由线程 1 持有的 ,但线程 1 从未以任何方法锁定 !这怎么可能?

提前致谢, DevCybran

编辑:添加使用的类加载器代码:

public class CraftElevatorsExtensionManager extends ClassLoader implements FilenameFilter, ElevatorsExtensionManager 
    private Map<String,ExtensionLoader> loaders = null;

    ...


    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException 
        for(ExtensionLoader loader: loaders.values()) 
            try 
                return loader.loadClassDirect(name); // line 85
             catch(ClassNotFoundException e)  
        
        throw new ClassNotFoundException();
    

    ...

    private class ExtensionLoader extends URLClassLoader 

        ...

        private Class<?> loadClassDirect(String name) throws ClassNotFoundException 
            Class<?> loadedClass = this.findLoadedClass(name);
            if(loadedClass==null) return this.findClass(name); // line 149
            return loadedClass;
        

        ...

        @Override
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException 
            // synchronized parent container first  - should prevent deadlocks
            synchronized(CraftElevatorsExtensionManager.this) 
                return super.loadClass(name, resolve); // line 231
            
        

    


使用 Java 6 u45。

【问题讨论】:

请提供围绕所示堆栈跟踪的代码。没有看到任何代码,在这里很难给出任何明确的答案 添加了所用类加载器的代码。 【参考方案1】:

我的猜测是你有一个 3way 死锁。应用程序中是否有其他线程? 我看到 pool-1-thread-1 持有 2 个锁:0x00000000f55dfc98 和 0x00000000f5601ac8 而 pool-1-thread-2 包含 0x00000000f55e2960、0x00000000f55dfc98 和其他一些 会不会是您拥有包含 0x00000000f5601ac8、0x00000000f55e2960 的 pool-1-thread-3 ? 或类似的东西。

【讨论】:

以上是关于Java:线程在没有获取锁的情况下持有锁的主要内容,如果未能解决你的问题,请参考以下文章

Java并发006使用层面:Lock锁机制全解析

java多线程知识总结

Jdk1.6之后对锁的优化

Java 死锁

锁volatileCAS的比较

什么是自旋锁