ThreadLocalとsynchronizedの違い


synchronizedキーワードは主にマルチスレッド共有データ同期の問題を解決する.
ThreadLocalの使用状況は主にマルチスレッドにおけるデータの同時発生による不一致の問題を解決する.
ThreadLocalとSynchonizedは、マルチスレッド同時アクセスを解決するために使用されます.しかし、ThreadLocalとsynchronizedには本質的な違いがあります.
synchronizedは、ロックのメカニズムを利用して、変数またはコードブロックを一時的に1つのスレッドしかアクセスできないようにします.一方、ThreadLocalは、各スレッドに変数のコピーを提供し、各スレッドがある時点で同じオブジェクトにアクセスしないようにし、複数のスレッドによるデータ共有を分離します.一方、Synchronizedは、複数のスレッド間で通信する際にデータ共有を得るために使用されます.
Synchronizedはスレッド間のデータ共有に使用され、ThreadLocalはスレッド間のデータ分離に使用されます.もちろんThreadLocalはsynchronizedに代わるものではなく、異なる問題ドメインを処理します.Synchronizedは、ThreadLocalよりも複雑な同期メカニズムを実現するために使用されます.
1、Javaにおけるsynchronizedの使い方
synchronizedキーワードを使用すると、マルチスレッド共有データ同期の問題を簡単に解決できます.
synchronizedキーワードは、関数の修飾子としてもよいし、関数内の文としてもよい.すなわち、通常の同期方法と同期文ブロックとして用いられる.さらに詳細な分類の場合、synchronizedはinstance変数、object reference(オブジェクト参照)、static関数、class literals(クラス名字面定数)に作用します.
   synchronized ; (lock) ; , , 。 

synchronizedの4つの使い方:
1.メソッド宣言時に使用する、スレッドはメンバーロックを取得する.
2.あるコードブロックに対して使用する、synchronizedの後に括弧、括弧の中に変数、スレッドが得たのはメンバーロックである.
3.synchronizedの後ろの括弧にオブジェクトがある場合、スレッドはオブジェクトロックを取得する.
4.synchronizedの後ろの括弧にはクラスがあり、この場合、スレッドはオブジェクトロックを得る.
2、java.lang.ThreadLocal()の使い方
一、概説
ThreadLocalって何ですか?実はThreadLocalはスレッドのローカル実装バージョンではなく、Threadではなくthreadlocalvariable(スレッドローカル変数)です.それをThreadLocalVarと命名するのがもっと適当かもしれません.スレッドローカル変数(ThreadLocal)の実際の機能は非常に簡単で、この変数を使用するスレッドごとに変数値のコピーを提供することであり、Javaの特殊なスレッドバインドメカニズムであり、他のスレッドのコピーと衝突することなく、各スレッドが独立して自分のコピーを変更することができる.
ThreadLocalはどのようにして各スレッドの変数のコピーを維持しますか?実装の構想は簡単で,ThreadLocalクラスには各スレッドの変数のコピーを格納するためのMapがある.
要約すると、マルチスレッドリソース共有の問題では、同期メカニズムは「時間で空間を変える」方式を採用し、ThreadLocalは「空間で時間を変える」方式を採用している.前者は1つの変数のみを提供し、異なるスレッドをキューに並べてアクセスさせ、後者は各スレッドに1つの変数を提供するため、互いに影響を及ぼさずに同時にアクセスすることができる.
二、API説明
ThreadLocal()
スレッドローカル変数を作成します.
T get()
このスレッドのローカル変数の現在のスレッドコピーの値を返します.このメソッドがスレッドで初めて呼び出された場合、このコピーを作成して初期化します.
protected T initialValue()
このスレッドのローカル変数の現在のスレッドの初期値を返します.このメソッドは、スレッドにアクセスして各スレッドのローカル変数を取得するたびに呼び出されます.すなわち、スレッドがget()メソッドを使用して初めて変数にアクセスしたときです.スレッドがgetメソッドより先にset(T)メソッドを呼び出す場合、initialValueメソッドはスレッドで呼び出されません.
実装がnullのみを返す場合.プログラマがスレッドのローカル変数をnull以外の値に初期化する場合は、ThreadLocalのサブクラスを作成し、このメソッドを書き直す必要があります.通常、匿名の内部クラスが使用されます.InitialValueの典型的なインプリメンテーションでは、適切なコンストラクションメソッドが呼び出され、新しいコンストラクションのオブジェクトが返されます.
void remove()
このスレッドのローカル変数の値を削除します.これにより、スレッドのローカル変数のストレージ要件を低減できます.このスレッドのローカル変数に再アクセスすると、デフォルトではinitialValueがあります.
void set(T value)
このスレッドローカル変数の現在のスレッドコピーの値を指定値に設定します.多くのアプリケーションはこの機能を必要とせず、initialValue()メソッドに依存してスレッドのローカル変数の値を設定します.
プログラムでは、通常、initialValueメソッドを書き換えて、特定の初期値を与えます.
三、典型例
四、まとめ
ThreadLocalの使用状況は主にマルチスレッドにおけるデータの同時発生による不一致の問題を解決する.
ThreadLocalは、各スレッドの同時アクセスデータにコピーを提供し、コピーにアクセスしてビジネスを実行する結果、メモリが消費され、スレッド同期によるパフォーマンス消費が大幅に減少し、スレッド同時制御の複雑さも減少します.
ThreadLocalでは原子型は使用できず、Object型のみ使用できます.ThreadLocalの使用はsynchronizedよりずっと簡単です.
五、ThreadLocal使用の一般手順
1.マルチスレッドのクラス(ThreadDemoクラスなど)に、スレッド間で分離処理が必要なオブジェクトxxxを保存するためのThreadLocalオブジェクトthreadXxxを作成します.
2.ThreadDemoクラスで、アクセスを分離するデータを取得するメソッドgetXxx()を作成し、メソッドでThreadLocalオブジェクトがnullの場合、new()アクセスタイプを分離するオブジェクトを作成し、適用するタイプに強制的に変換する.
3、ThreadDemoクラスのrun()メソッドでは、getXxx()メソッドで操作するデータを取得し、スレッドごとに1つのデータオブジェクトに対応し、いつでもこのオブジェクトが操作されることを保証します.
springは種々のDAOテンプレートクラスによって開発者が種々のデータ持続技術を使用する難易度を低減することを知っている.これらのテンプレートクラスは、スレッドが安全です.つまり、複数のDAOは、競合することなく同じテンプレートインスタンスを多重化できます.
テンプレートクラスを使用して最下位のデータにアクセスします.永続化テクノロジーによっては、テンプレートクラスはデータ接続またはセッションのリソースをバインドする必要があります.しかし、これらのリソース自体は非スレッドで安全であり、つまり、同じ時点で複数のスレッドで共有することはできません.
テンプレートクラスは、リソースプールを介してデータ接続またはセッションを取得しますが、リソースプール自体がデータ接続またはセッションのキャッシュ問題を解決し、データ接続またはセッションのスレッドセキュリティの問題ではありません.
従来の経験によれば、オブジェクトが非スレッドで安全である場合、マルチスレッド環境では、オブジェクトへのアクセスはsynchronizedを使用してスレッド同期する必要があります.しかしSpringのDAOテンプレートクラスではスレッド同期メカニズムは採用されていません.スレッド同期は同時アクセスを制限し、パフォーマンスの損失が大きいからです.
また、コード同期によるパフォーマンス・セキュリティの問題の解決には課題があり、実装の難易度が何倍も向上する可能性があります.テンプレート類はいったいどんな魔法の神功を仰ぎ、同期を必要とせずにスレッドの安全を解消できるのだろうか.答えはThreadLocal!
ThreadLocalはSpringにおいて重要な役割を果たし、request役割ドメインを管理するBean、トランザクション管理、タスクスケジューリング、AOPなどのモジュールにそれらの姿が現れ、重要な役割を果たしている.Springトランザクション管理の下位テクノロジーを理解するには、ThreadLocalが攻略しなければならない山頭の砦です.
ソース:http://blog.csdn.net/huyongl1989/article/details/8088841