(回る)Spring同時訪問スレッドの安全性問題(高度総括)

6717 ワード

以下の記録はspring中の合併に対するまとめです.理論分析はSpring中のSingletonモードのスレッド安全を参考にして、先に見ることを提案します.
springにおける合併訪問問題:
一般的には無状態のBeanだけがマルチスレッド環境で共有できることを知っています.SpringではほとんどのBeanはsingletonの役割領域として宣言できます.状態のあるbeanに対しては?Springは、いくつかの(例えば、Request Contact Holder、Transation SynconizationManager、Locaree Contactext Holderなど)のスレッド以外のセキュリティ状態のbeanを、ThreadLocalで処理し、それらをスレッドの安全な状態にすることができます.
状態のあるビーンを使っても、プロトタイプを使って注入するたびに新たにビーンを作成し、マルチスレッドでは互いに影響がない.
 
状態があるとデータストア機能があります.ステータスオブジェクト(Stteful Bean)とは、インスタンス変数があるオブジェクトで、データを保存することができます.非スレッドセキュリティです.呼び出しの間に状態を保持しません.
無状態は一回の操作で、データを保存できません.無状態オブジェクトとは、インスタンス変数がないオブジェクトです. .データを保存できません.不変類です.スレッドが安全です.
無状態のBeanは不変のモードを使用するのに適しており、技術は単一の例のモードであり、このように実例を共有し、性能を向上させることができる.
 
状態のビームがあり、マルチスレッド環境では安全ではないので、Prottypeプロトタイプのモデルに適しています.Prototype:beanに対する要求ごとに新しいbeanのインスタンスを作成します.
Servletシステム構造はJavaマルチスレッド機構の上に構築されており、そのライフサイクルはWebコンテナが担当している.一つのServletクラスは、Applicationには一例しか存在しない.つまり、複数のスレッドがこの例を使用している.これは一例モードの応用である.Service層、Dao層のようにデフォルトのsingletonを使えばいいです.Service類にもdaoという属性がありますが、dao類は状態情報がない、つまり不変類に相当しますので、影響はありません.Struts 2におけるアクションはUser、BizEntityといった例示的なオブジェクトがあるため、ステータス情報があり、マルチスレッド環境では安全ではないので、Struts 2のデフォルトの実装はProttypeモードである.Springでは、Struts 2のアクションのうち、scopeはプロトタイプのスコープとして機能します.(単一の例のモード−一例のレジストリ実装とthreadLocal−状態のあるbeanとの関係を処理することができる)
また、クライアントからバックグラウンドに転送されたcontroller-->service-->Daoは、これらのオブジェクトは一例ですが、これらの例のオブジェクトはバックグラウンドに転送されたエンティティbeanを処理しても問題がないですか?答:「エンティティbeanは一例ではない」ということです.springに任せて管理していません.毎回手動でNewに出てきた「EMakeType=new EMakeType()」.ですから、データを提出した業務処理類はマルチスレッドで共有されていますが、データを共有しているわけではありません.データは、スレッドごとに独自のものがあります.したがって、データの面ではスレッド同期に関する問題は起こらない.
(本明細書では、プロジェクト開発において、エンティティbeanに対するマルチスレッド内の処理を追加します.1.エンティティbeanについては、一般的に方法パラメータの形式で伝達されます.(パラメータは局所変数です.)マルチスレッド間には影響がありません.2.状態のあるbeanに対して直接プロトタイプのモデルを使って解決するところがあります.3.beanを使うところはnewで作成できます.
しかし、それらはDaoの中のxxDao、またはcontrollerの中のxxServiceであり、これらのオブジェクトは一例ではスレッド同期の問題が発生します.しかし、これらの対象は複数のプロセスに同時に訪問されますが、それらの中には通常メンバー変数が含まれていません.そのDaoの中のibatisDaoはフレーム内にカプセル化されています.すでにテストされています.スレッド同期の問題はありません.だから問題が発生したのは私達自身のシステムの中の業務の対象です.だから私達はこれらの業務の対象の中で独立したメンバー変数を要してはいけません.
springはこれらの有状態beanに対してThreadLocal保持変数を使用しています.「変数だけです.スレッド同期の問題はメンバー変数の相互反発によって問題が発生します.」
spring同時訪問スレッドの安全に関する2つのブログのまとめには、上記のような結論が得られます.
Spring MVCはデフォルトではSingletonなので、潜在的な安全潜在的な危険が発生します.根本的な核心はinstanceの変数保持状態の問題です.これは各requestが来ることを意味しています.システムは元のinstanceで処理しています.これは二つの結果をもたらします.
まず、私たちは毎回Controllerを作成しなくてもいいです.二つは対象の作成とごみ収集の時間を減らすことです.Controllerのinstanceが一つしかないので、複数のスレッドが同時に起動すると、その中のinstance変数(プライベート変数として理解できる)はスレッドの安全ではなく、データの問題が発生します.もちろん大多数の場合、私達はスレッドセキュリティの問題、例えばdao、serviceなどを考慮する必要はありません.beanでインスタンス変数を宣言した場合を除いて.したがって、我々は、spring mvcのcontrllerを使用する場合、controllerにインスタンス変数を定義することを避けるべきである(singletonの唯一の良くないことは、単一の例の変数が問題になりやすく、以下に解決策がある).例えば:
publicclassControllerextendsAbstractCommandController{
......
protectedModelAndView handle(HttpServletRequest request,HttpServletResponse response,
Object command,BindException errors)throwsException{
company =................;
}
protectedCompany company;
}
 
ここでは変数companyが宣言されています.ここではスレッドの安全性を併発する問題があります.コントローラが一例形式を使用し、かつコントローラにプライベート変数aがあり、すべてが同じcontrollerに要求された場合、使用するa変数は共用であり、つまりある要求の中でこの変数aが修正された場合、他の要求の中でこの修正の内容を読むことができる.いくつかの解決方法があります.1、コントローラではインスタンス変数を使用しない(メソッドパラメータを使用して解決できます.記事Spring Bean Scopeを参照してください.ステータスのBenがない状態のBeanを参照してください.)2、コントローラの役割領域を単例からプロトタイプに変更します.すなわちspringプロファイルControllerでscope="prototype"を宣言します.毎回新しいcontroller 3、を作成します.ControllerにThreadLocal変数を使う
このいくつかの方法は良いものと悪いものがあります.まず、開発者は高いプログラミングレベルと思想意識を持っています.
第二は、コンテナが自動的に各要求に対して一例を生成し、JVMによってゴミ回収を行い、スレッドの安全を実現した.
第一の方法を使用する利点は、インスタンスオブジェクトが一つしかないことであり、すべての要求は、インスタンスオブジェクトを呼び出し、速度とパフォーマンスは第二のものより優れていなければならず、悪いところは、プログラマ自身がインスタンス変数の状態保持問題を制御する必要があることである.第二は、要求毎に一例を作成するため、より多くのメモリ空間を消費する.
スプリングを使ってwebを開発する時は、デフォルトのController、Dao、Serviceは一例です.
 
【1】SprigMVCマルチスレッド環境において、オブジェクトの安全性はどのように保証されますか?
コードは以下の通りです
@Request Mapping("/user")@Conttrler Class UserConttrolller{@Resource UserSerService userSerService;@Request Mapping("/add")publicvoid testA(Useruser){userSerServicevice.add){dedededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededededeerService)Class UserService{publicstaticMap<Integer、User>usersCache=newHashMap<String、User>();publicvoid add(User user){usersCache.put(user.getId()))}このセグメントコードは、usersCacheオブジェクトがスレッドの安全ではないため、静的なグローバル共有オブジェクトです.複数のスレッドが同時にaddメソッドを呼び出すと、ユーザオブジェクトが上書きされることがあります.id対応オブジェクトが一致しないということです.これはマルチスレッドプログラムで最も頻繁に発生することです.
だから、使ってもいいです. Collectionツール同期Map.
static Map users Cache=Collection s.synchronized Map(new HashMap);
研究してみます.Springのソースコードは、一般的なオープンソースのフレームに大量に封入されています.
ヒベルナでのsession Factoryは、org.springframe ebook.orm.hibernate 3.annotations.AnnotationSession FactoryBenを使用していますが、AnnotationSession Factory Bernの父類Locarsion FactoryBenでは、安全性を多く定義しています.
 
プロブレブレラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクラクベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンベンディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディディアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアreadLocal()•prvatestaticfinalThreadLocal<Object>configTimeRegionFactoryHolder=newThreadLocal<Object>();prvatestaticfinalThreadLocacacacacal<CachProvider>configTimeCachPrProvidedededeHolder=newTaTaTaTaTaTadedededededededededededededededededededededededededededededededededededededededededededer=neneneneneneneaaadedededededededededededededededededededededededededededededededewThreadLocal<LobHandler>();
)