对于Hibernate的openSession方法为什么不是线程安全的源码理解

首先,先明确几个概念。

1、局部变量不会受多线程影响。

2、成员变量会受到多线程影响。
多个线程调用的同一个对象的同一个方法:
如果方法里无成员变量,不受任何影响,
如果方法里有成员变量,只有读操作,不受影响,存在赋值操作,有影响。

第一点
SessionFactory和Session都是接口,SessionFactoryImpl和SessionImpl是其实现。

第二点
SessionFactoryImpl里的openSession方法如下,其中的 new SessionImpl(…)存在线程不安全的因素。

    @Override
        public Session openSession() {
            log.tracef( "Opening Hibernate Session.  tenant=%s, owner=%s", tenantIdentifier, sessionOwner );
            final SessionImpl session = new SessionImpl(
                    connection,
                    sessionFactory,
                    sessionOwner,
                    getTransactionCoordinator(),
                    autoJoinTransactions,
                    sessionFactory.settings.getRegionFactory().nextTimestamp(),
                    interceptor,
                    flushBeforeCompletion,
                    autoClose,
                    connectionReleaseMode,
                    tenantIdentifier
            );

            for ( SessionEventListener listener : listeners ) {
                session.getEventListenerManager().addListener( listener );
            }

            return session;
        }

第三点
通过观察下面SessionImpl的源码实现,可以发现在构造方法内部出现了对于成员变量的赋值的操作,所以线程不安全。

    SessionImpl(
            final Connection connection,
            final SessionFactoryImpl factory,
            final SessionOwner sessionOwner,
            final TransactionCoordinatorImpl transactionCoordinator,
            final boolean autoJoinTransactions,
            final long timestamp,
            final Interceptor interceptor,
            final boolean flushBeforeCompletionEnabled,
            final boolean autoCloseSessionEnabled,
            final ConnectionReleaseMode connectionReleaseMode,
            final String tenantIdentifier) {
        super( factory, tenantIdentifier );
        this.timestamp = timestamp;
        this.sessionOwner = sessionOwner;
        this.interceptor = interceptor == null ? EmptyInterceptor.INSTANCE : interceptor;
        this.actionQueue = new ActionQueue( this );
        this.persistenceContext = new StatefulPersistenceContext( this );

        this.autoCloseSessionEnabled = autoCloseSessionEnabled;
        this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;

        if ( transactionCoordinator == null ) {
            this.isTransactionCoordinatorShared = false;
            this.connectionReleaseMode = connectionReleaseMode;
            this.autoJoinTransactions = autoJoinTransactions;

            this.transactionCoordinator = new TransactionCoordinatorImpl( connection, this );
            this.transactionCoordinator.getJdbcCoordinator().getLogicalConnection().addObserver(
                    new ConnectionObserverStatsBridge( factory )
            );
        }
        else {
            if ( connection != null ) {
                throw new SessionException( "Cannot simultaneously share transaction context and specify connection" );
            }
            this.transactionCoordinator = transactionCoordinator;
            this.isTransactionCoordinatorShared = true;
            this.autoJoinTransactions = false;
            if ( autoJoinTransactions ) {
                LOG.debug(
                        "Session creation specified 'autoJoinTransactions', which is invalid in conjunction " +
                                "with sharing JDBC connection between sessions; ignoring"
                );
            }
            if ( connectionReleaseMode != transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnectionReleaseMode() ) {
                LOG.debug(
                        "Session creation specified 'connectionReleaseMode', which is invalid in conjunction " +
                                "with sharing JDBC connection between sessions; ignoring"
                );
            }
            this.connectionReleaseMode = transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnectionReleaseMode();

            // add a transaction observer so that we can handle delegating managed actions back to THIS session
            // versus the session that created (and therefore "owns") the transaction coordinator
            transactionObserver = new TransactionObserver() {
                @Override
                public void afterBegin(TransactionImplementor transaction) {
                }

                @Override
                public void beforeCompletion(TransactionImplementor transaction) {
                    if ( isOpen() && flushBeforeCompletionEnabled ) {
                        SessionImpl.this.managedFlush();
                    }
                    beforeTransactionCompletion( transaction );
                }

                @Override
                public void afterCompletion(boolean successful, TransactionImplementor transaction) {
                    afterTransactionCompletion( transaction, successful );
                    if ( isOpen() && autoCloseSessionEnabled ) {
                        managedClose();
                    }
                    transactionCoordinator.removeObserver( this );
                }
            };

            transactionCoordinator.addObserver( transactionObserver );
        }

        loadQueryInfluencers = new LoadQueryInfluencers( factory );

        if (factory.getStatistics().isStatisticsEnabled()) {
            factory.getStatisticsImplementor().openSession();
        }

      if ( TRACE_ENABLED )
           LOG.tracef( "Opened session at timestamp: %s", timestamp );
    }

当然,这些只是博主粗浅的理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值