ThreadLocal天生为解决相同变量的访问冲突问题, 所以这个对于spring的默认单例bean的多线程访问是一个完美的解决方案。spring也确实是用了ThreadLocal来处理多线程下相同变量并发的线程安全问题。
- 要想实现jdbc事务, 就必须是在同一个连接对象中操作, 多个连接下事务就会不可控, 需要借助分布式事务完成。那spring 如何保证数据库事务在同一个连接下执行的呢?
- DataSourceTransactionManager 是spring的数据源事务管理器, 它会在你调用getConnection()的时候从数据库连接池中获取一个connection, 然后将其与ThreadLocal绑定, 事务完成后解除绑定。这样就保证了事务在同一连接下完成。
事务开始阶段
public static void bindResource(Object key, Object value) throws IllegalStateException {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Assert.notNull(value, "Value must not be null");
Map<Object, Object> map = resources.get();
// set ThreadLocal Map if none found
if (map == null) {
map = new HashMap<>();
resources.set(map);
}
Object oldValue = map.put(actualKey, value);
- ThreadLocal存储的为DataSource生成的actualKey为key值和ConnectionHolder作为value值封装成的Map。
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
- 将 DBResource 和 ConnectionHolder分别作为KV存入 map
Object oldValue = map.put(actualKey, value);
事务结束阶段
@Nullable
private static Object doUnbindResource(Object actualKey) {
Map<Object, Object> map = resources.get();
if (map == null) {
return null;
}
Object value = map.remove(actualKey);
// Remove entire ThreadLocal if empty...
if (map.isEmpty()) {
resources.remove();
}
- 获取ThreadLocalMap
resources.get();
- 删除map 的Entry并移除
Object value = map.remove(actualKey);
// Remove entire ThreadLocal if empty...
if (map.isEmpty()) {
resources.remove();
}
学习更多:
ThreadLocal 面试六连问,你能 Hold 住吗?
ThreadLocal-面试必问深度解析
Spring事务之如何保证同一个Connection对象
公众号"会讲历史的程序员",欢迎关注
网友评论