Java同時プログラミング:ThreadLocalの理解
3065 ワード
前言
JAvaメモリモデル
JAva仮想マシンは、実際のコンピュータ構造を模倣し、java内の各変数、インスタンスにメモリ空間を割り当てる.主に次のものがあります.メソッド領域:クラス情報、定数、静的変数、インスタントコンパイラコンパイル後のコードデータ.メソッド領域は、実行時定数プールを含む:字面量、シンボル参照 スタック:スレッド共有メモリ領域、オブジェクトインスタンス を格納プログラムカウンタ: 仮想マシンスタック:スレッドプライベートデータ領域で、各メソッドが実行されるとスタックフレームが作成され、メソッドの変数テーブル、オペランドスタック、ダイナミックリンク、戻り値、戻りアドレスなどの情報が格納されます. ローカルメソッドスタック:nativeコードに関連するスレッドプライベートデータ領域.
ThreadLocalは、各スレッドで変数のコピーを作成します.つまり、各スレッドの内部に変数があり、スレッドの内部のどこでも使用できます.スレッド間では互いに影響しません.これにより、スレッドのセキュリティの問題がなく、プログラムの実行性能にも深刻な影響を与えません.ThreadLocalは上記の問題を解決できますが、各スレッドにコピーが作成されているため、メモリの使用量がThreadLocalを使用しないよりも大きいなど、リソースの消費量を考慮します.
ThreadLocalクラス
ThreadLocalは、各変数のコピーをどのように作成しますか.
現在のスレッドのThreadLocalMapを取得し、取得に成功するとvalue値を返し、失敗するとsetInitialValue()を呼び出します.
threadLoaclsはThreadLoaclMapタイプで、ThreadLoaclクラスの内部クラスです.
EntryクラスはThreadLocalMapの内部クラスであり、WeakReferenceから継承され、キー値としてThreadLocalタイプが使用されます.各スレッドThreadの内部にはThreadLocal.ThreadLocalMapタイプのメンバー変数threadLocalsがあり、このthreadLocalsは実際の変数コピーを格納するために使用され、キー値は現在のThreadLocal変数であり、valueは変数コピー(すなわちTタイプの変数) である. ThreadではthreadLocalsが空であり、ThreadLocal変数によってget()メソッドまたはset()メソッドが呼び出されると、ThreadクラスのthreadLocalsが初期化され、現在のThreadLocal変数をキー値とし、ThreadLocalが保存するレプリカ変数をvalueとしてthreadLocalsに格納される. 現在のスレッドで、コピー変数を使用する場合はgetメソッドでthreadLocalsで検索できます.
一般的には、各スレッドは作成時に独自のThreadLocalタイプのプライベートオブジェクトを作成し、このプライベートオブジェクトをThreadのmapのkey値とすることで、対応するvalueを見つけることができ、スレッド間のvalueコピーが相互に影響しない役割を果たすことができます.
JAvaメモリモデル
JAva仮想マシンは、実際のコンピュータ構造を模倣し、java内の各変数、インスタンスにメモリ空間を割り当てる.主に次のものがあります.
ThreadLocalは、各スレッドで変数のコピーを作成します.つまり、各スレッドの内部に変数があり、スレッドの内部のどこでも使用できます.スレッド間では互いに影響しません.これにより、スレッドのセキュリティの問題がなく、プログラムの実行性能にも深刻な影響を与えません.ThreadLocalは上記の問題を解決できますが、各スレッドにコピーが作成されているため、メモリの使用量がThreadLocalを使用しないよりも大きいなど、リソースの消費量を考慮します.
ThreadLocalクラス
ThreadLocalは、各変数のコピーをどのように作成しますか.
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
現在のスレッドのThreadLocalMapを取得し、取得に成功するとvalue値を返し、失敗するとsetInitialValue()を呼び出します.
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
threadLoaclsはThreadLoaclMapタイプで、ThreadLoaclクラスの内部クラスです.
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal> k, Object v) {
super(k);
value = v;
}
}
....
}
EntryクラスはThreadLocalMapの内部クラスであり、WeakReferenceから継承され、キー値としてThreadLocalタイプが使用されます.
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
一般的には、各スレッドは作成時に独自のThreadLocalタイプのプライベートオブジェクトを作成し、このプライベートオブジェクトをThreadのmapのkey値とすることで、対応するvalueを見つけることができ、スレッド間のvalueコピーが相互に影響しない役割を果たすことができます.