# DbWhereTest **Repository Path**: qdbp/db-where-test ## Basic Information - **Project Name**: DbWhereTest - **Description**: No description available - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-07-18 - **Last Updated**: 2021-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 遇到一个没想明白的问题。
一个类的静态字段是当前类的子类,多线程同时实例化该类和子类时,线程卡住。 问题可以重现,不是必现,概率80%以上。 git clone https://gitee.com/qdbp/db-where-test.git
cd db-where-test/code
test.bat
有一个类DbWhere,它的一个静态字段NONE是DbWhere自身的子类: ```java public class DbWhere { /** 没有查询条件的空Where **/ public static final DbWhere NONE = new ReadonlyWhere(); public DbWhere() { log(this.getClass(), "DbWhere()"); } 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()"); } } /** 只读查询条件 **/ public class ReadonlyWhere extends EmptiableWhere { public ReadonlyWhere() { log(this.getClass(), "DbWhere()"); } } ``` 两个测试的线程类 ```java public class DbWhereThread extends Thread { public void run() { new DbWhere(); } } ``` ```java public class EmptiableWhereThread extends Thread { public void run() { new EmptiableWhere(); } } ``` 测试1,多线程实例化父类DbWhere,没有问题 ```java public class DbWhereTest1 { public static void main(String[] args) { for (int i = 0; i < 3; i++) { new DbWhereThread().start(); } } } ``` 测试2,多线程实例化子类EmptiableWhere,没有问题 ```java public class DbWhereTest2 { public static void main(String[] args) { for (int i = 0; i < 3; i++) { new EmptiableWhereThread().start(); } } } ``` 测试3,先实例化DbWhere,再多线程同时实例化父类和子类,没有问题 ```java 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,多线程同时实例化父类和子类,**线程卡住了** ```java 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看,都卡在构造函数这里 ```java "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.(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的一个字段,绕过了这个问题。
但是造成问题的原理不清楚,记录一下。