作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
学习必须往深处挖,挖的越深,基础越扎实!
阶段1、深入多线程
阶段2、深入多线程设计模式
阶段3、深入juc源码解析
码哥源码部分
码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】
码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】
码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】
码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】
打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】
处理回滚流程图
传播机制图
AbstractPlatformTransactionManager的cleanupAfterCompletion回滚后处理
看上去很像没多少东西,其实里面涉及好多呢,比如如果是新的事务同步状态的话,要把线程的同步状态清除了,如果是新事务的话,进行数据清除,线程的私有资源解绑,重置连接自动提交,隔离级别,是否只读,释放连接等。如果有挂起的事务,还要把这个事务给恢复,其实就是把属性设置回去。
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
status.setCompleted();
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();//线程同步状态清除
}
if (status.isNewTransaction()) {//是新事务的话,进行数据清除,线程的私有资源解绑,重置连接自动提交,隔离级别,是否只读,释放连接等
doCleanupAfterCompletion(status.getTransaction());
}
if (status.getSuspendedResources() != null) {//有挂起的事务要恢复
if (status.isDebug()) {
logger.debug("Resuming suspended transaction after completion of inner transaction");
}
Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
}
}
TransactionSynchronizationManager的clear清除同步状态
就是前面我们设置的线程私有的一些属性。
public static void clear() {
synchronizations.remove();
currentTransactionName.remove();
currentTransactionReadOnly.remove();
currentTransactionIsolationLevel.remove();
actualTransactionActive.remove();
}
DataSourceTransactionManager的doCleanupAfterCompletion清除连接相关操作
这里就是做跟连接相关的操作,比如重置自动提交啊,只读属性啊,解绑数据源啊,释放连接啊,清除链接持有器属性啊。
@Override
protected void doCleanupAfterCompletion(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
// Remove the connection holder from the thread, if exposed.
if (txObject.isNewConnectionHolder()) {//接触数据源和连接的绑定
TransactionSynchronizationManager.unbindResource(obtainDataSource());
}
// Reset connection.
Connection con = txObject.getConnectionHolder().getConnection();
try {
if (txObject.isMustRestoreAutoCommit()) {
con.setAutoCommit(true);//充实连接自动提交属性
}
DataSourceUtils.resetConnectionAfterTransaction(//重置隔离级别,是否只读等
con, txObject.getPreviousIsolationLevel(), txObject.isReadOnly());
}
catch (Throwable ex) {
logger.debug("Could not reset JDBC Connection after transaction", ex);
}
if (txObject.isNewConnectionHolder()) {
if (logger.isDebugEnabled()) {
logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
}
DataSourceUtils.releaseConnection(con, this.dataSource);//释放连接
}
//连接持有器属性清除
txObject.getConnectionHolder().clear();
}
TransactionSynchronizationManager的unbindResource解绑数据源
public static Object unbindResource(Object key) throws IllegalStateException {
//获取数据源
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Object value = doUnbindResource(actualKey);//获取解绑的连接持有器
if (value == null) {
throw new IllegalStateException(
"No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
}
return value;
}
其实就是从线程私有变量resources
中删除了,这个是个map
,因为可能有多个数据源绑定多个连接的。
DataSourceUtils的resetConnectionAfterTransaction重置连接
其实就是重置事务隔离状态和是否只读。
public static void resetConnectionAfterTransaction(
Connection con, @Nullable Integer previousIsolationLevel, boolean resetReadOnly) {
...
try {
if (previousIsolationLevel != null) {
...
con.setTransactionIsolation(previousIsolationLevel);
}
if (resetReadOnly) {
...
con.setReadOnly(false);
}
}
catch (Throwable ex) {
logger.debug("Could not reset JDBC Connection after transaction", ex);
}
}
DataSourceUtils的releaseConnection释放连接
释放JDBC
连接。
public static void releaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) {
try {
doReleaseConnection(con, dataSource);
}
catch (SQLException ex) {
logger.debug("Could not close JDBC Connection", ex);
}
catch (Throwable ex) {
logger.debug("Unexpected exception on closing JDBC Connection", ex);
}
}
doReleaseConnection释放连接
获取连接持有器,释放连接,然后关闭连接。
public static void doReleaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) throws SQLException {
if (con == null) {
return;
}
if (dataSource != null) {
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);//获取连接持有器,如果前面解除绑定非就拿不到了
if (conHolder != null && connectionEquals(conHolder, con)) {//如果连接持有器能拿到的话
// It's the transactional Connection: Don't close it.
conHolder.released();
return;
}
}
doCloseConnection(con, dataSource);//关闭连接
}
doCloseConnection关闭连接
如果不是SmartDataSource
类型就关闭连接了。
public static void doCloseConnection(Connection con, @Nullable DataSource dataSource) throws SQLException {
if (!(dataSource instanceof SmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
con.close();
}
}