最近公司内某个项目出现了因并发问题导致的多数据源串掉的问题,经研究找到了如下解决方案
A线程切换指定数据源并挂起
B线程使用了默认数据源,A线程先于B线程,结果B线程使用了从库数据源(health_bi)
DynamicDataSourceContextHolder中NamedInheritableThreadLocal导致两个数据源共用同一数据源队列Deque<String> 且NamedInheritableThreadLocal会出现将此子线程的值复制到主线程中
InheritableThreadLocal的类注释
This class extends ThreadLocal to provide inheritance of values from parent thread to child thread: when a child thread is created, the child receives initial values for all inheritable thread-local variables for which the parent has values. Normally the child's values will be identical to the parent's; however, the child's value can be made an arbitrary function of the parent's by overriding the childValue method in this class.
Inheritable thread-local variables are used in preference to ordinary thread-local variables when the per-thread-attribute being maintained in the variable (e.g., User ID, Transaction ID) must be automatically transmitted to any child threads that are created.
经翻译为
此类扩展ThreadLocal以提供从父线程到子线程的值继承:当创建子线程时,子线程接收父线程具有值的所有可继承线程本地变量的初始值。通常情况下,孩子的值与父母的值相同;但是,通过重写该类中的childValue方法,可以使子级的值成为父级的任意函数。
当变量中维护的每线程属性(例如,用户ID、事务ID)必须自动传输到创建的任何子线程时,可继承线程本地变量优先于普通线程本地变量。
子线程创建的时候会获取所有父线程的值。而子线程的值又会传递给父线程,所以就相当于所有子线程的值是共享的,这个问题才会出现。而跟代码的时候你会发现其实所有线程的ArrayDeque都是指向同一个地址
当用new Thread()创建线程时,会走下面的代码,那么inheritThreadLocals就会是true
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
升级dynamic-datasource最新版本,使用NamedThreadLocal,NamedThreadLocal并无其他操作仅仅是命名
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。