スレッドセーフの問題
スレッドセーフの問題を解決する
1.最初にスレッドの不安定さの問題を観察します
- 次のコード:
本来预期结果n = 0;但是因为线程的安全问题,导致会出现其他结果,只有有不是预期结果的情况出现,我们就不能说它是安全的;
- n ++とn–はアトミックではないため;
package 线程安全问题;
/**
* 这样线程存在很大的安全问题,因为结果不一定是预期结果
*/
public class ThreadDemo {
private static int n = 0;
private static final int COUNT = 100000;
static class Adder extends Thread{
@Override
public void run() {
for (int i = 0;i < COUNT;i++){
n++;
}
}
}
static class Suber extends Thread{
@Override
public void run() {
for (int i = 0;i < COUNT;i++){
n--;
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Adder();
Thread t2 = new Suber();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(n);
}
}
2.スレッドの不安定さの理由
1.アトミシティ
- 単一の命令はアトミックである必要があります-途中でスレッドの切り替えはありません
- 複数の命令を切り替えても副作用は発生しません。
たとえば、今見たn ++(アトミックではない)は、実際には3つの操作で構成されています。
- メモリからCPUにデータを読み取ります。
- データの更新を実行します。
- データをCPUに書き戻します。
共通の原子性
//下面的这几个是具备原子性的
int a = 10;
boolean a =true;
byte/short/char/float
(因为JVM是以32 bit作为基本单位进行操作的)
//下面这俩个是不具备原子性的
long a = 10;
double a = 10.0;
2.可視性
- 効率を上げるために、JVMは実行プロセス中に可能な限り作業メモリー内のデータを実行しますが、これは問題を引き起こします。共有変数は複数のスレッド間で時間内に変更できません。これは可視性の問題です。
3.コードシーケンス(並べ替え)
1.コードの並べ替えとは
- コードの一部は次のようになります。
- フロントデスクに移動して、USBフラッシュドライブを取り外します
- 教室に行って10分間の宿題を書く
- フロントデスクに行き、宅配便を取り外します
- シングルスレッドの状況では、JVMとCPUの命令セットが最適化します。たとえば、1-> 3-> 2の方法で実行しても問題ありません。フォアグラウンドを1回だけ実行できます。 。これは、命令の並べ替えと呼ばれます。
2.コードの並べ替えはマルチスレッドにどのような問題をもたらしますか?
- 今の例では、シングルスレッドの状況は問題なく、最適化は正しいですが、マルチスレッドの状況には問題があります。問題は何ですか。宿題を書いてから10分以内に別のスレッドから宅配便が解放されたか、誰かによって変更された可能性があります。手順を並べ替えると、コードが間違ってしまいます。
3.スレッドセーフについて
- 1.データ共有のないスレッド間では、スレッドセーフの問題は発生しません。
- 2.データの共有があっても、限り何の変更操作がないので、そこも必ずしもないスレッドの安全性の問題も。