Revert use of Map::computeIfAbsent in thread and tx scopes

Issues gh-25038 and gh-25618 collectively introduced a regression for
thread-scoped and transaction-scoped beans.

For example, given a thread-scoped bean X that depends on another
thread-scoped bean Y, if the names of the beans (when used as map keys)
end up in the same bucket within a ConcurrentHashMap AND an attempt is
made to retrieve bean X from the ApplicationContext prior to retrieving
bean Y, then the use of Map::computeIfAbsent in SimpleThreadScope
results in recursive access to the same internal bucket in the map.

On Java 8, that scenario simply hangs. On Java 9 and higher,
ConcurrentHashMap throws an IllegalStateException pointing out that a
"Recursive update" was attempted.

In light of these findings, we are reverting the changes made to
SimpleThreadScope and SimpleTransactionScope in commits 50a4fdac6e and
148dc95eb1.

Closes gh-25801
This commit is contained in:
Sam Brannen
2020-09-25 10:55:32 +02:00
parent a532c527dd
commit f5d36aa47a
4 changed files with 34 additions and 12 deletions

View File

@@ -12,10 +12,18 @@
</property>
</bean>
<bean id="threadScopedObject" class="org.springframework.beans.testfixture.beans.TestBean" scope="thread">
<property name="spouse" ref="threadScopedObject2" />
<!--
NOTE: The bean names removeNodeStatusScreen and removeNodeStatusPresenter are seemingly
quite odd for TestBean instances; however, these have been chosen due to the fact that
they end up in the same bucket within a HashMap/ConcurrentHashMap initialized with the
default initial capacity.
For details see: https://github.com/spring-projects/spring-framework/issues/25801
-->
<bean id="removeNodeStatusScreen" class="org.springframework.beans.testfixture.beans.TestBean" scope="thread">
<property name="spouse" ref="removeNodeStatusPresenter" />
</bean>
<bean id="threadScopedObject2" class="org.springframework.beans.testfixture.beans.TestBean" scope="thread" />
<bean id="removeNodeStatusPresenter" class="org.springframework.beans.testfixture.beans.TestBean" scope="thread" />
</beans>