1 Star 0 Fork 0

qdbp/DbWhereTest

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

遇到一个没想明白的问题。
一个类的静态字段是当前类的子类,多线程同时实例化该类和子类时,线程卡住。

问题可以重现,不是必现,概率80%以上。

git clone https://gitee.com/qdbp/db-where-test.git
cd db-where-test/code
test.bat

有一个类DbWhere,它的一个静态字段NONE是DbWhere自身的子类:

public class DbWhere {

    /** 没有查询条件的空Where **/
    public static final DbWhere NONE = new ReadonlyWhere();

    public DbWhere() {
        log(this.getClass(), "DbWhere<init>()");
    }

    static void log(Class<?> clazz, String msg) {
        System.out.println(Thread.currentThread().getName() + ' ' + clazz.getSimpleName() + '-' + msg);
    }
}

/** 允许为空的查询条件 **/
public class EmptiableWhere extends DbWhere {
    public EmptiableWhere() {
        log(this.getClass(), "DbWhere<init>()");
    }
}

/** 只读查询条件 **/
public class ReadonlyWhere extends EmptiableWhere {
    public ReadonlyWhere() {
        log(this.getClass(), "DbWhere<init>()");
    }
}

两个测试的线程类

public class DbWhereThread extends Thread {
    public void run() {
        new DbWhere();
    }
}
public class EmptiableWhereThread extends Thread {
    public void run() {
        new EmptiableWhere();
    }
}

测试1,多线程实例化父类DbWhere,没有问题

public class DbWhereTest1 {

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new DbWhereThread().start();
        }
    }
}

测试2,多线程实例化子类EmptiableWhere,没有问题

public class DbWhereTest2 {

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new EmptiableWhereThread().start();
        }
    }
}

测试3,先实例化DbWhere,再多线程同时实例化父类和子类,没有问题

public class DbWhereTest3 {

    public static void main(String[] args) {
        new DbWhere();
        for (int i = 0; i < 3; i++) {
            new DbWhereThread().start();
            new EmptiableWhereThread().start();
        }
    }
}

测试4,多线程同时实例化父类和子类,线程卡住了

public class DbWhereTest4 {

    public static void main(String[] args) {
        System.out.println("DbWhereTest4");
        for (int i = 0; i < 3; i++) {
            new DbWhereThread().start();
            new EmptiableWhereThread().start();
        }
    }

}

从线程Dump看,都卡在构造函数这里

"Thread-5" #16 prio=5 os_prio=0 tid=0x00000000226f0000 nid=0x6284 in Object.wait() [0x000000002477f000]
   java.lang.Thread.State: RUNNABLE
        at EmptiableWhereThread.run(EmptiableWhereThread.java:3)

   Locked ownable synchronizers:
        - None

"Thread-4" #15 prio=5 os_prio=0 tid=0x00000000226ed800 nid=0x5d20 in Object.wait() [0x000000002467f000]
   java.lang.Thread.State: RUNNABLE
        at DbWhereThread.run(DbWhereThread.java:3)

   Locked ownable synchronizers:
        - None

"Thread-3" #14 prio=5 os_prio=0 tid=0x00000000226ec800 nid=0x4640 in Object.wait() [0x000000002457f000]
   java.lang.Thread.State: RUNNABLE
        at EmptiableWhereThread.run(EmptiableWhereThread.java:3)

   Locked ownable synchronizers:
        - None

"Thread-2" #13 prio=5 os_prio=0 tid=0x00000000226e8000 nid=0x409c in Object.wait() [0x000000002447f000]
   java.lang.Thread.State: RUNNABLE
        at DbWhereThread.run(DbWhereThread.java:3)

   Locked ownable synchronizers:
        - None

"Thread-1" #12 prio=5 os_prio=0 tid=0x00000000226e5800 nid=0x6760 in Object.wait() [0x000000002437e000]
   java.lang.Thread.State: RUNNABLE
        at EmptiableWhereThread.run(EmptiableWhereThread.java:3)

   Locked ownable synchronizers:
        - None

"Thread-0" #11 prio=5 os_prio=0 tid=0x00000000226e2000 nid=0x62c8 in Object.wait() [0x000000002427e000]
   java.lang.Thread.State: RUNNABLE
        at DbWhere.<clinit>(DbWhere.java:4)
        at DbWhereThread.run(DbWhereThread.java:3)

   Locked ownable synchronizers:
        - None

DbWhere定义成这个结构,是想实现避免出现预期之外的条件为空:
1、直接new DbWhere(),则条件不允许完全为空;
2、如果预知条件为空,就要用DbWhere.NONE;
3、如果有可能为空,则使用new EmptiableWhere()。

目前已经通过删除EmptiableWhere,把emptiable作为DbWhere的一个字段,绕过了这个问题。
但是造成问题的原理不清楚,记录一下。

MIT License Copyright (c) 2021 qdbp Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

暂无描述 展开 收起
Java
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/qdbp/db-where-test.git
git@gitee.com:qdbp/db-where-test.git
qdbp
db-where-test
DbWhereTest
master

搜索帮助