[解決済み】atomic / volatile / synchronizedの違いは何ですか?
質問
アトミック/ボラタイル/シンクロナイゼーションは内部でどのように動作するのですか?
次のコードブロックの違いは何ですか?
コード1
private int counter;
public int getNextUniqueIndex() {
return counter++;
}
コード2
private AtomicInteger counter;
public int getNextUniqueIndex() {
return counter.getAndIncrement();
}
コード3
private volatile int counter;
public int getNextUniqueIndex() {
return counter++;
}
は
volatile
は、次のように動作するのでしょうか?です。
volatile int i = 0;
void incIBy5() {
i += 5;
}
と同じです。
Integer i = 5;
void incIBy5() {
int temp;
synchronized(i) { temp = i }
synchronized(i) { i = temp + 5 }
}
2つのスレッドが同時に同期ブロックに入ることはできないと思うのですが...正しいですか?もしそうだとしたら、どのようにして
atomic.incrementAndGet()
がなくても動作します。
synchronized
? また、スレッドセーフですか?
また、volatile変数/atomic変数に対する内部での読み書きの違いは何でしょうか?何かの記事で、スレッドが変数のローカルコピーを持っていると読みましたが、それは何でしょうか?
どのように解決するのですか?
具体的にどのようにするのかというご質問ですね。 内部動作 ということで、こちらです。
同期を取らない
private int counter;
public int getNextUniqueIndex() {
return counter++;
}
基本的にはメモリから値を読み出し、インクリメントしてメモリに戻すというものです。これはシングルスレッドでは動作しますが、マルチコア、マルチCPU、マルチレベルキャッシュの時代となった現在では、正しく動作しないでしょう。まず、レースコンディション(複数のスレッドが同時に値を読み取ることができる)が発生し、さらに可視性の問題も発生します。値が " にしか保存されないかもしれません。 ローカル 他のCPU/コア(つまりスレッド)からは見えません。このため、多くの人が ローカルコピー スレッド内の変数の 非常に安全ではありません。この人気のある、しかし壊れたスレッド停止コードを考えてみてください。
private boolean stopped;
public void run() {
while(!stopped) {
//do some work
}
}
public void pleaseStop() {
stopped = true;
}
追加
volatile
から
stopped
を変更すると、正常に動作します。
stopped
を経由して
pleaseStop()
メソッドを使用すると、その変更を作業中のスレッドの
while(!stopped)
のループになります。ちなみにこれはスレッドに割り込む良い方法でもありません、参照してください。
何もせずにずっと動いているスレッドを停止させる方法
そして
特定のjavaスレッドを停止する
.
AtomicInteger
private AtomicInteger counter = new AtomicInteger();
public int getNextUniqueIndex() {
return counter.getAndIncrement();
}
は
AtomicInteger
クラスはCAS (
コンペア・アンド・スワップ
これらは、現在の値が他の何かと等しい(そして正常に返される)場合にのみ、特定の変数を変更することを可能にします。ですから
getAndIncrement()
は、実際にはループで実行されます(実際の実装は簡略化されています)。
int current;
do {
current = get();
} while(!compareAndSet(current, current + 1));
つまり、基本的には、読み込み、増分された値の格納を試み、成功しない場合(値が
current
を読み込んで、再試行します。このとき
compareAndSet()
はネイティブコード(アセンブリ)で実装されています。
volatile
同期なし
private volatile int counter;
public int getNextUniqueIndex() {
return counter++;
}
このコードは正しくありません。これは可視性の問題を解決するものです (
volatile
に加えられた変更が他のスレッドに表示されることを確認します。
counter
) が、まだレースコンディションが残っています。これは、これまで
説明
プリ/ポストインクリメントはアトミックではありません。
の唯一の副作用は
volatile
は"です。
水洗
キャッシュは、他のすべての関係者が最も新しいバージョンのデータを見ることができるようにします。これはほとんどの場合において厳しすぎる。
volatile
はデフォルトではありません。
volatile
同期を取らない場合 (2)
volatile int i = 0;
void incIBy5() {
i += 5;
}
上記と同じ問題ですが、さらに悪いことに
i
は
private
. レースコンディションはまだ存在しています。なぜ問題なのでしょうか?例えば、2つのスレッドが同時にこのコードを実行した場合、出力は次のようになります。
+ 5
または
+ 10
. しかし、その変化を見ることは保証されています。
複数の独立した
synchronized
void incIBy5() {
int temp;
synchronized(i) { temp = i }
synchronized(i) { i = temp + 5 }
}
驚いたことに、このコードも不正確です。というか、完全に間違っています。まず第一に、あなたは同期を
i
は、変更されようとしている(しかも。
i
はプリミティブなので、一時的に同期をとっているのでしょう。
Integer
オートボックスで作成された...) 完全な欠陥です。と書くこともできます。
synchronized(new Object()) {
//thread-safe, SRSLy?
}
2つのスレッドが同じ
synchronized
ブロック
同じロックで
. この場合(あなたのコードでも同様)、ロックオブジェクトは実行ごとに変更されるので
synchronized
は事実上何の効果もありません。
たとえ、最終変数(または
this
) を使って同期をとっていますが、このコードはまだ正しくありません。2つのスレッドが最初に
i
から
temp
を同期的に使用します(ローカルに同じ値を持つ
temp
に新しい値を代入する。
i
(例えば、1から6まで)、もう一方は同じことを(1から6まで)します。
読み込みから値の代入までの同期が必要です。最初の同期には何の効果もありません。
int
はアトミックです)、2番目も同様です。私の意見では、これらが正しい形です。
void synchronized incIBy5() {
i += 5
}
void incIBy5() {
synchronized(this) {
i += 5
}
}
void incIBy5() {
synchronized(this) {
int temp = i;
i = temp + 5;
}
}
関連
-
[解決済み] javax.mail.MessagingException: SMTPホストに接続できませんでしたか?
-
[解決済み] javaでAnnotation Inheritanceのようなものはあるのでしょうか?
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] アトミック属性と非アトミック属性の違いは何ですか?
-
[解決済み] プロセスとスレッドの違いは何ですか?
-
[解決済み] wait()とsleep()の違いについて
-
[解決済み] シンクロナイズド」とはどういう意味ですか?
-
[解決済み】Javaにおけるvolatileとsynchronizedの違いについて
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] このフォーマット(Tue Jul 13 00:00:00 CEST 2010)の日付をJavaの日付に変換する方法(文字列はalfrescoのプロパティに由来しています)
-
[解決済み] enumのordinalを使用するのは良い習慣ですか?
-
[解決済み] Oracle DB : java.sql.SQLException: 閉じた接続
-
[解決済み] javascriptでExpression言語を使うには?
-
[解決済み] 型の不一致:ArrayListからListへの変換ができない
-
[解決済み] JDBC タイプの方言マッピングがありません。1111
-
[解決済み] Mavenです。JARは空になります - 含有するためにマークされたコンテンツがありません
-
[解決済み] JavaFX 同じパッケージ内なのに「場所が必要です。
-
[解決済み】Volatile booleanとAtomicBooleanの比較
-
[解決済み] Volatile Vs Atomic [重複](揮発性対原子)。