共有可変データへのアクセスを同期できない場合、たとえ変数がアトミックに読み取りおよび書き込み可能であっても、悲惨な結果が生じる可能性があります。
スレッド同期の問題を考えてみましょう。スレッド同期のために、Java クラス ライブラリは Thread.stop メソッドを提供しますが、このメソッドは本質的に安全ではないため、推奨する価値はありません。以下のプログラムのようなポーリングを使用するとよいでしょう。
次のようにコードをコピーします。
java.util.concurrent.TimeUnitをインポートします。
パブリック クラス StopThread {
/**
* @param 引数
*/
プライベート静的ブール値 stopRequested;
public static void main(String[] args)
中断例外をスローします{
スレッドの背景スレッド = 新しいスレッド(新しい Runnable() {
@オーバーライド
public void run() {
int i = 0;
while(!stopRequested){
i++;
System.out.println(i);
}
}
});
背景スレッド.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
このプログラムが約 1 秒間実行された後、メイン スレッドが stopRequested を true に設定し、バックグラウンドの新しいスレッドが停止するのではないかと思われるかもしれません。実際はそうではありません。バックグラウンド スレッドはこの変更を認識できないからです。値が異なるため、無限にループし続けます。これは、データが同期されていないことの結果です。それでは、これを同期的に実行してみましょう。
次のようにコードをコピーします。
java.util.concurrent.TimeUnitをインポートします。
パブリック クラス StopThread {
/**
* @param 引数
*/
プライベート静的ブール値 stopRequested;
private static synchronized void requestStop(){
stopRequested = true;
}
プライベート静的同期ブール値 stopRequested(){
stopRequested を返します。
}
public static void main(String[] args)
中断例外をスローします{
スレッドの背景スレッド = 新しいスレッド(新しい Runnable() {
@オーバーライド
public void run() {
int i = 0;
while(!stopRequested()){
i++;
System.out.println(i);
}
}
});
背景スレッド.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
これにより、データの同期が実現されます。書き込みメソッド (requestStop) と読み取りメソッド (stopRequested) の両方が同期される必要があることに注意してください。そうでないと、まだ本当の意味で同期されていません。
さらに、volatile 変数修飾子を使用すると、同期タスクをより簡単に完了できます。
次のようにコードをコピーします。
java.util.concurrent.TimeUnitをインポートします。
パブリック クラス StopThread {
/**
* @param 引数
*/
private static volatile boolean stopRequested;
public static void main(String[] args)
中断例外をスローします{
スレッドの背景スレッド = 新しいスレッド(新しい Runnable() {
@オーバーライド
public void run() {
int i = 0;
while(!stopRequested){
i++;
System.out.println(i);
}
}
});
背景スレッド.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}