回答編集履歴

4

2番目の例の回答分も訂正

2017/06/09 04:25

投稿

KSwordOfHaste
KSwordOfHaste

スコア18394

test CHANGED
@@ -94,7 +94,7 @@
94
94
 
95
95
 
96
96
 
97
- 上記のようなクラスは「valueを参照したらそれ以前の最後のset結果が得られる」ことを保証できます。しかしもしvolatileが付いていなければ保証がなくなり、スレッドセーフとはいえなくなります。コンパイラィールドのアクセスを最適化しまい、過去の時点でアクセスしたvalueの値を再利用してしまうかも知れないからです
97
+ 上記のようなクラスは「valueを参照したらそれ以前の最後のset結果が得られる」ことを保証できます。しかしもしvolatileが付いていなければ保証がなくなり、スレッドセーフとはいえなくなります。例えset呼出し後にvalueを参照したとしても、メモリェンスによるアクセス保証がない場合、あるスレッドでvalue更新後に別のスレッドで更新後の新の値が読めるという保証がないからです。(コンパイラーの最適化によって過去のvalueのアクセス結果が使いわされるといこともあるかも知れません)
98
98
 
99
99
 
100
100
 

3

訂正:

2017/06/09 04:25

投稿

KSwordOfHaste
KSwordOfHaste

スコア18394

test CHANGED
File without changes

2

追記2

2017/06/09 04:19

投稿

KSwordOfHaste
KSwordOfHaste

スコア18394

test CHANGED
@@ -1,4 +1,26 @@
1
- 追記yohhoyさんご指摘により最初の例の不具合(volatileが抜けている)ことがわかりましたので修正いたしました。失礼しました。
1
+ 追記: yohhoyさんご指摘により最初の例の不具合(volatileが抜けている)ことがわかりましたので修正いたしました。失礼しました。
2
+
3
+
4
+
5
+ 追記2: 恥かきついでに自分の考えの間違いの説明を試みます。
6
+
7
+
8
+
9
+ 1. synchronizedでメソッドは排他できる。
10
+
11
+ 2. countUpが実行の完了時にgetが他のスレッドから呼び出されてもcountUp完了まで待たされる
12
+
13
+ 3. countUpが実行を完了していればフィールドの値は0->2に書き換わる
14
+
15
+ 4. その後getが動けば1が読めることはなく、必ず2が読める**(と考えた)**
16
+
17
+
18
+
19
+ 例えば、複数のプロセッサが並行して動作している場合に、プロセッサーごとに独立して動作するキャッシュがあったとすると、例え同一空間上のメモリーを参照したとしても、メモリー・フェンスなしではどのタイミングの値が読めるかの保証がないということだと思います。自分はコンパイラーの最適化によって最新の値を常に参照するかどうかという観点でvolatileを考えていたのですが、メモリー・フェンスの動作について把握できていませんでした。
20
+
21
+
22
+
23
+ (この解釈にも間違いがあるかも知れません。もしそうならご指摘いただければ非常にありがたいです。)
2
24
 
3
25
 
4
26
 

1

訂正

2017/06/09 04:15

投稿

KSwordOfHaste
KSwordOfHaste

スコア18394

test CHANGED
@@ -1,3 +1,11 @@
1
+ 追記:yohhoyさんご指摘により最初の例の不具合(volatileが抜けている)ことがわかりましたので修正いたしました。失礼しました。
2
+
3
+
4
+
5
+ ---
6
+
7
+
8
+
1
9
  スレッドセーフかどうかは「そのクラス(あるいはそのクラスのインスタンス)」に複数のスレッドから機能にアクセスした際に「矛盾のない結果を保証する」ことを意味します。
2
10
 
3
11
 
@@ -10,7 +18,7 @@
10
18
 
11
19
  class Counter1 {
12
20
 
13
- private int count;
21
+ private volatile int count;
14
22
 
15
23
 
16
24