ケーススタディ
package com.duyang.thread.basic.basethread;
/**
* @author :jiaolian
* @date :Created in 2020-12-16 14:02
* @description:线程不安全分析
* @modified By:
* 公众号:叫练
*/
public class ThreadUnsafe {
public static void main(String[] args) {
Thread task = new Task();
Thread threadA = new Thread(task,"A");
Thread threadB = new Thread(task,"B");
Thread threadC = new Thread(task,"C");
Thread threadD = new Thread(task,"D");
Thread threadE = new Thread(task,"E");
threadA.start();
threadB.start();
threadC.start();
threadD.start();
threadE.start();
}
private static class Task extends Thread {
int count = 5;
@Override
public void run() {
/**
* jvm分3步骤;
* 1.获取count(从主内存获取值)
* 2.count减1(在各自寄存器完成)
* 3.保存count(刷新到主内存)
*
* 说下可能执行的过程...
* A线程获取cpu的count值为5,A线程先减去1,保存count值为4刷新到主内存,此时还没有执行System.out.println count
* 切换到B线程,此时B线程的count值为4,因为B线程是从主内存取的,B线程count值减去1为3,此时刷新到主内存,主内存值变为3
* 切换到A线程,执行System.out.println count=3
* 切换到B线程,执行System.out.println count=3
* 情况就是这样的
*
*/
count--;
System.out.println(Thread.currentThread().getName() + " "+count);
}
}
}
考えられる結果
結果は次の図です(結論1図)
こんな感じで
はい、その通りですが、スレッドAとスレッドBのカウント値が両方とも3に等しい可能性があります。以下で分析してみましょう。
詳細な分析
コード内の45行、つまり、JVMでは、3つのステップに分割できます。
- カウント値を取得します(メインメモリから値を取得します)
- カウントマイナス1(それぞれのレジスタで完了)
- カウントを保存します(メインメモリにフラッシュします)
詳細には、A、Bは実際に機械の処理中です
- AスレッドはCPUカウント値5を取得し、Aスレッドは最初に1を減算し、カウント値4を保存してメインメモリにフラッシュします。現時点では、カウントを出力するためのSystem.out.printlnは実行されていません。値。以下に示すように
- Bスレッドに切り替えます。このとき、Bスレッドはメインメモリからアクセスされるため、Bスレッドのカウント値は4になり、Bスレッドのカウント値は1から3だけ減算され、メインメモリはで更新されます。今回はメインメモリの値が3になります。
- Aスレッドに切り替え、System.out.println count = 3を実行します
- Bスレッドに切り替え、System.out.println count = 3を実行します
- CDEスレッドは正常に実行されます
<結論1画像>の実行プロセスです。
結論として
マルチスレッドの安全性は常に非常に重要なトピックであり、誰もができるだけ早くそれを理解して習得できることを願っています。
私はリアンと呼ばれています。もっとリアンに電話してください。みんなが私と話し合ったり交換したりすることを歓迎します。できるだけ早く返信します。気に入っています。