Java併發(四)----執行緒執行原理

|舊市拾荒|發表於2023-05-05

1、執行緒執行原理

1.1 棧與棧幀  

Java Virtual Machine Stacks (Java 虛擬機器棧 JVM)

我們都知道 JVM 中由堆、棧、方法區所組成,其中棧記憶體是給誰用的呢?其實就是執行緒,每個執行緒啟動後,虛擬機器就會為其分配一塊棧記憶體。

  • 每個棧由多個棧幀(Frame)組成,對應著每次方法呼叫時所佔用的記憶體

  • 每個執行緒只能有一個活動棧幀,對應著當前正在執行的那個方法

單執行緒示例程式碼

public class TestFrames {
    public static void main(String[] args) {
        method1(10); // 斷點處
    }
​
    private static void method1(int x) {
        int y = x + 1;
        Object m = method2();
        System.out.println(m);
    }
​
    private static Object method2() {
        Object n = new Object();
        return n;
    }
}

在打斷點處,可以看到一個棧幀

Java併發(四)----執行緒執行原理

執行到method1,可以看到新起了一個棧幀

Java併發(四)----執行緒執行原理

當執行到method2時,可以看到又新起了一個棧幀

Java併發(四)----執行緒執行原理

由於是棧,隨著的程式的執行,後面開啟的棧幀會先被銷燬,直至main棧幀被銷燬,此刻程式執行完成。

對應圖解:

Java併發(四)----執行緒執行原理

記憶體釋放後

Java併發(四)----執行緒執行原理

具體就是:

1.將編譯好的位元組碼載入到jvm的方法區記憶體中
2.jvm啟動一個main的主執行緒,cpu核心就準備執行主執行緒的程式碼了,給主執行緒分配自己的棧記憶體【args、區域性變數、返回地址、所記錄】,每個執行緒的棧裡面還有個程式計數器
程式計數器的作用:當cpu要執行哪行程式碼了,就去這個裡面去要
3.把主方法的裡面程式碼行放到程式計數器
4.主方法呼叫的是method1的方法,為method1分配棧記憶體,裡面儲存這個方法裡面區域性變數,返回地址,這些變數是分配記憶體時,會把空間預留好
5.將method1的第一行讀到程式計數器讓cpu執行
6.methode1下一行呼叫method2()方法,建立他的棧記憶體
7.把Object n = new Object()這行程式碼讀取到計數器,在隊中建立物件
8.method2()將返回地址給m,方法執行完就可以釋放掉method2()的棧記憶體
9.一層層方法結束後,依次釋放掉每個方法執行緒

現在來看看多執行緒下的棧與棧幀

public class TestFrames {
    public static void main(String[] args) {
        Thread t1 = new Thread(){
            @Override
            public void run() {
                method1(20);// 斷點處
            }
        };
        t1.setName("t1");
        t1.start();
        method1(10);// 斷點處
    }
​
    private static void method1(int x) {
        int y = x + 1;
        Object m = method2();
        System.out.println(m);
    }
​
    private static Object method2() {
        Object n = new Object();
        return n;
    }
}
​

在第一個斷點處

Java併發(四)----執行緒執行原理

可以看到多個執行緒同時執行中,我們可以選擇具體的執行緒來檢視執行狀況並且往下執行,具體的讀者可以自行實踐。

1.2 執行緒上下文切換(Thread Context Switch)

因為以下一些原因導致 cpu 不再執行當前的執行緒,轉而執行另一個執行緒的程式碼(簡單來說就是從使用cpu到不使用cpu

  • 執行緒的 cpu 時間片用完

  • 垃圾回收

  • 有更高優先順序的執行緒需要執行

  • 執行緒自己呼叫了 sleep、yield、wait、join、park、synchronized、lock 等方法

當 Context Switch(上下文切換) 發生時,需要由作業系統儲存當前執行緒的狀態,並恢復另一個執行緒的狀態,Java 中對應的概念就是程式計數器(Program Counter Register),它的作用是記住下一條 jvm 指令的執行地址,是執行緒私有的

  • 狀態包括程式計數器、虛擬機器棧中每個棧幀的資訊,如區域性變數、運算元棧、返回地址等

  • Context Switch 頻繁發生會影響效能,因為執行緒數不是越多越好。

 

相關文章