序文
最近、春のプロジェクトを開始するときにデッドロックの問題に遭遇しました。 jstackを使用してスレッドスタックを取得する場合、2つのスレッドにデッドロックがあることがわかります。
解決策プロセス:
DefaultSingletonBeanRegistry.getSingleton()のソースコードは次のとおりです。この方法では、SingletonObjectsをロックする必要があることがわかります。
2番目のxxx.subject.core.cache.datalocalcacheinit.afterpropertiessetのソースコードは次のとおりです。
このBeanが初期化されたときに、スレッドを起動し、別のBeanのinitData()メソッドを呼び出してデータベースからデータをロードすることがわかります。データがロードされた後、Datalocalcacheinit Beanの初期化は完全であると見なされます。
上記のスタックから、スプリング容器がBeanを初期化すると、SingletonObjectsオブジェクトがロックされることがわかります。 afterPropertiesSet()メソッドにスレッドを開きます。これにより、最終的にスプリングがトリガーして別の豆をロードします。最初のスレッド(スプリングを初期化するメインスレッド)はロックをリリースしておらず、2番目のスレッド(単独で開くスレッド)もシングルトンオブジェクトオブジェクトロックを取得する必要があり、デッドロックが発生します。示されている現象は、スプリング容器がそこに詰まっており、すべての豆の初期化を完了できないことです。
私たちのプロジェクトの実際のコードと非常によく似た例を見てみましょう。 FirstBeanはConfigelperでメソッドを呼び出します:
Public Class FirstBean IntializingBean {@Override public void afterpropertiesset()throws exception {system.out.println( "First Bean is Initializing ...."); blockingqueue queue = new arrayblockingqueue(10);スレッドスレッド= newスレッド(){@Override public void run(){confighelper.dosomething(); queue.add(1); }}; thread.start(); queue.take(); System.out.println( "First Get Data ...."); }} confighelperコードは次のとおりです。BeanFactoryを通じて別のBeanを取得します
パブリッククラスのコンフィグレーパーは、beanfactoryaware {private static beanfactory Factory; @Override public void setBeanFactory(BeanFactory BeanFactory)Throws BeanSexception {this.Factory = BeanFactory; } public static void dosomething(){secondbean bean =(secondbean)factory.getbean( "second"); bean.say(); }} SecondBeanコードは次のように簡単です。
public class secondbean {public void say(){system.out.println( "secondbean ..."); }}Spring構成ファイルと起動コードは次のとおりです。実行中にデッドロックを見つけることができます:
<?xml version = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean Id = ""> id = "second"> </bean> </beans> public class main {public static void main(string [] args){applicationContext context = new filesystemxmlapplicationContext( "src/main/java/net/aty/spring/deadlock/deadlock.xml");スプリングが初期化されると、スレッドを起動すると、Spring(BeanFactoryAware/initializingBeanなど)が提供するいくつかの拡張ポイントでBeanを取得すると、コンテナはデッドロックされます。春の初期化シングルトンビーンズ(ほとんどの豆はシングルトン)がロックを追加するためです。 1豆が初期化されたときにロックが解放されておらず、別のスレッドがスプリングロードビーンを再びトリガーすると、デッドロックが表示されます。
上記の問題を解決することは簡単です。FirstBeanは論理的にConfighelperとSecondBeanに依存しますが、Springの論理的な関係は示していません。 SpringがFirstBeanを初期化するときは、 afterPropertiesSet()を入力します。この方法では、スレッドがオンになったときに他の2つの豆の負荷をトリガーします。スプリングの依存性を示し、最初にスプリングロードコンフィアパーとセカンドビーンを許可する必要があります。
<bean id = "config" depend-on = "second"> </bean> <bean id = "first" depress-on = "config"> </bean> <bean id = "second"> </bean>
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。