More Related Content Similar to Java 並行処理の基礎update1 Similar to Java 並行処理の基礎update1 (20) More from Kazuhiro Eguchi More from Kazuhiro Eguchi (8) Java 並行処理の基礎update13. 自己紹介
✤ twitter: hakurai
✤ Javaとか
✤ JavaFX!JavaFX!
9. 変数について
✤ 変数とは記憶領域のこと 変数1
変数2
✤ Javaの変数は型を持つ 変数3
✤ プリミティブ型
✤ 参照型
✤ クラス型
✤ インターフェイス型
✤ 配列型
✤ null型
10. メイン・メモリと作業メモリ
✤ 変数は、すべてのスレッドから共有されるメイン・メモリ中に保持さ
れる。
✤ すべてのスレッドには作業メモリという、スレッドによって使用や代
入が行われる変数の作業コピーを保持する領域が用意される。
Java仮想マシン仕様 第2版 359Pより
12. 変数は作業メモリに転送される
スレッド1 スレッド2
✤ メイン・メモリから変数が作業メモリ
実行エンジン 実行エンジン
に転送される
変数A
100
変数B
変数A 変数B
100
変数C 変数D
13. スレッド1上で変数Aに値を代入すると
スレッド1 スレッド2
✤ スレッド1の作業エンジンが変数Aに
実行エンジン 実行エンジン
200を代入する
変数A
200
変数B
✤ Java仮想マシンの仕様上メイン・メモ
リに書き込むタイミングは自由
変数A 変数B
100
変数C 変数D
14. この状態でスレッド2が変数Aを読み込むと
スレッド1 スレッド2
✤ スレッド2の作業メモリ上の変数Aは古
実行エンジン 実行エンジン
いまま
変数A 変数A
200 100
変数B
✤ スレッド2からは変数Aの値が100に見
える
変数A 変数B
100
変数C 変数D
17. synchronizedの役割(相互排除)
✤ すべてのオブジェクトにはモニタが存在する
✤ モニタを取得してオブジェクトをロックするのがsynchronized
✤ 同時にモニタを取得できるのは一つのスレッドだけ
✤ オブジェクトのロックを取得できたスレッドのみ処理を実行させる
✤ synchronized文を抜けるとロックは自動的に解放される
19. ロックと変数(メモリの可視性)
✤ スレッドが任意のロックに対してアンロックを実行する場合、最初に
その作業メモリ中のすべての代入値をメイン・メモリにコピーしてお
かなければならない
✤ ロックは、スレッドの作業メモリからすべての変数をフラッシュする
かのように振る舞う
Java仮想マシン仕様 第2版 364Pより
20. ロックと変数に関する規則1
✤ 変数のスレッドに対する代入と、それに続くアンロックの間には、必
ずストアが介在し、更にそのストアに対応する書き込みは、必ずアン
ロックに先立って行わなければならない
✤ つまり、作業メモリ内で変更された変数はアンロック前にメイン・メ
モリへのコピーが完了していなければならない
21. ロックと変数に関する規則2
✤ 任意のロックLに対するスレッドTによるロックLと、それに続く変数Vに対するスレッ
ドTによる使用やストアの間には、必ず変数Vに対する代入やロードが介在する
✤ さらにロード時には、メイン・メモリからみた場合、そのロードに対する読み込み
は、必ずロックの後に行わなければならない。
✤ つまり、ロック後に使用する変数は、使用する前にメイン・メモリからロードされな
ければならない
✤ もしくは、代入によって変数を上書きする
23. ロックの例
✤ モニタの解放後に他のスレッドから最新の値が見えることを保証する
private final Object lock = new Object();
private List<String> list;
private String get(int index){
synchronized (lock){
return list.get(index);
}
}
24. ダメな例
private final Object lock = new Object();
private List<String> list;
public void add(String text){
synchronized (lock){
list.add(text);
}
}
public String get(int index){
return list.get(index);
}
25. ダメな例
private final Object lock = new Object();
private List<String> list;
public void add(String text){
synchronized (lock){
list.add(text);
}
}
public String get(int index){
return list.get(index);
}
陳腐化したデータ
26. ダメな例
private final Object lock = new Object();
private List<String> list;
public void add(String text){
synchronized (lock){
最新の状態のlistが見えることを保証していない
list.add(text);
・予期しない値が返される
}
・IllegalArgumentException
}
public String get(int index){
return list.get(index);
}
陳腐化したデータ
27. アンロックが実行されると
スレッド1 スレッド2
✤ メイン・メモリの変数Aの値は200に更
実行エンジン 実行エンジン
新される
変数A 変数A
200 100
変数B
変数A 変数B
200
変数C 変数D
28. ロックが実行されると
スレッド1 スレッド2
✤ スレッド2の作業メモリの変数Aの値は
実行エンジン 実行エンジン
200に更新される
変数A 変数A
200 200
変数B
変数A 変数B
200
変数C 変数D
30. volatileの役割
✤ フィールドをvolatileとして宣言することによって、Javaのメモリ・モ
デルはすべてのスレッドから見てその変数の値の整合性が保たれるこ
とを保証する
Java言語仕様 第3版 177Pより
31. volatile変数に対する規則
✤ 変数がvolatileとして宣言されている場合、各スレッドの動作に次の
制約が追加される
✤ 変数Vに対するスレッドTによる使用は、変数Vに対するスレッドTに
よる以前の動作がロードである場合にのみ許される
✤ 変数Vに対するスレッドTによるロードは、変数Vに対するスレッドT
による次の動作が使用である場合にのみ許される
Java仮想マシン仕様 第2版 364Pより
33. volatile変数の使用
スレッド1 スレッド2
✤ 使用される前にメイン・メモリから最
実行エンジン 実行エンジン
新の値がコピーされる
変数A 変数A
200 200
変数B
変数A 変数B
200
変数C 変数D
34. volatile変数の代入
スレッド1 スレッド2
✤ 代入された直後に最新の値がメイン・
実行エンジン 実行エンジン
メモリにコピーされる
変数A 変数A
200 100
変数B
変数A 変数B
200
変数C 変数D
36. リオーダーの禁止
✤ 非volatile変数の読み書きとの順序替え(reordering)の禁止
private int num = 0;
private volatile boolean initialized;
public void run(){
num = 100;
initialized = true;
}
37. finalフィールド
✤ finalフィールドによって、プログラマは同期化を用いることなく、ス
レッド・セーフな不変オブジェクトを実装できるようになる
✤ 生成中のオブジェクトへの参照は、該当オブジェクトのコンストラク
タが完了する前に他のスレッドから観測される場所に書き込んではい
けない
Java言語仕様 第3版 500Pより
38. 不変クラスの例
public final class Test {
private String text;
private List<Integer> integerList;
public Test(String text, List<Integer> integerList) {
this.text = text;
this.integerList = new ArrayList<>(integerList);
}
public String getText() {
return text;
}
public List<Integer> getIntegerList() {
return new ArrayList<>(integerList);
}
}
39. 不変クラスの例??
public final class Test {
private String text;
private List<Integer> integerList;
public Test(String text, List<Integer> integerList) {
this.text = text;
this.integerList = new ArrayList<>(integerList);
}
public String getText() {
return text;
}
public List<Integer> getIntegerList() {
return new ArrayList<>(integerList);
}
}
40. 不変クラスの(ダメな)例
public final class Test {
private String text;
private List<Integer> integerList;
public Test(String text, List<Integer> integerList) {
this.text = text;
this.integerList = new ArrayList<>(integerList);
}
public String getText() {
return text;
}
public List<Integer> getIntegerList() {
return new ArrayList<>(integerList);
}
}
41. 不変クラスの作成ガイドライン
✤ すべてのフィールドがfinalである
✤ クラスがfinalとして宣言されている
✤ 作成時にthis 参照がコンストラクター外部に渡されない
✤ 配列、コレクションなどの可変オブジェクトや、Date などの可変クラスへの参照を含
むフィールドが以下の条件を満たす
✤ privateである
✤ 返されないか、呼び出し側に公開されない
✤ 参照の対象となるオブジェクトへの唯一の参照である
✤ 参照するオブジェクトの状態を、そのオブジェクトが作成された後で変更しない
Javaの理論と実践: 可変性か、不変性か?
http://www.ibm.com/developerworks/jp/java/library/j-jtp02183/index.html
42. 不変クラスの(ダメな)例
public final class Test {
private String text;
private List<Integer> integerList;
public Test(String text, List<Integer> integerList) {
this.text = text;
this.integerList = new ArrayList<>(integerList);
}
public String getText() {
return text;
}
public List<Integer> getIntegerList() {
return new ArrayList<>(integerList);
}
}
43. 不変クラスの(ダメな)例
public final class Test {
private String text;
private List<Integer> integerList;
public Test(String text, List<Integer> integerList) {
this.text = text;
this.integerList = new ArrayList<>(integerList);
}
public String getText() { nullの可能性がある
return text;
}
public List<Integer> getIntegerList() {
return new ArrayList<>(integerList);
}
}
44. 不変クラスの(ダメな)例
public final class Test {
private String text;
private List<Integer> integerList;
public Test(String text, List<Integer> integerList) {
this.text = text;
this.integerList = new ArrayList<>(integerList);
}
public String getText() { nullの可能性がある
return text;
}
public List<Integer> getIntegerList() { 例外が発生する可能性
return new ArrayList<>(integerList);
} がある
}
45. 不変クラスの(正しい)例
public final class Test {
private final String text;
private final List<Integer> integerList;
public Test(String text, List<Integer> integerList) {
this.text = text;
this.integerList = new ArrayList<>(integerList);
}
public String getText() {
return text;
}
public List<Integer> getIntegerList() {
return new ArrayList<>(integerList);
}
}
Editor's Notes \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n