堆和棧的區別

堆與棧

關於堆和棧的問題,對於熟悉C++的同窗來講可能理解的比較清楚,可是因爲Java的一切對象都是在堆上,所以有時候可能反而會比較迷惑,好比:php

爲何要分堆和棧?程序員

堆和棧的區別是什麼?編程

爲何堆是線程共享的而棧不是?數組

不少懂一點Java的人甚至是懂一點編程的人都知道內存通常分爲堆和棧,棧由系統進行關係,而堆由程序員本身管理,...balabala,基本任何一本語言基礎書都會提到這些特色,可是你有想過爲何嗎?安全

爲何要分堆和棧

之因此要區分堆和棧,是因爲程序須要兩種不一樣特性的內存形似而肯定的。在C++中,新建一個對象有兩種方式,靜態分配動態分配微信

靜態分配數據結構

通常來講,靜態分配用於初始化已知對象大小的時候,好比int a[10];若是咱們可以肯定這個數組是10個,咱們可使用這種方式。這種方式所須要的內存在編譯期間便可肯定,所以操做系統即可以預先肯定所指定大小內存給變量,而且能夠在變量生命週期結束後自動釋放。多線程

動態分配spa

然而在某些場景下,可能須要根據某些狀況來申請內存,好比int* a =new int[count];而變量count可能就來自於某個配置文件或者用戶手動輸入的值。這個時候操做系統就沒法再預先肯定內存大小,而且不執行到new int[count]這一行代碼的時候,是沒法知道所要分配的內存大小,所以操做系統分出一塊內存,用來進行動態分配。而且規定,動態分配的內存須要由客戶端自行管理。操作系統

Java 中的堆

因爲JVM規範中規定,JVM中的一切對象都存儲在堆上(內存逃逸除外)。所以在Java中並不存在對象的靜態分配,所以堆和棧的來源看似就很是理所固然。可是要明白,在操做系統中,堆和棧的出現的原因。

堆和棧的區別

知道了爲何要區分堆和棧,再來看看堆和棧的區別。

  • 堆是運行時肯定內存大小,而棧在編譯時便可肯定內存大小

    理由即是第一節中提到的,這是區分堆和棧的初衷

  • 堆內存由用戶管理(Java中由JVM管理),棧內存會被自動釋放

  • 棧實現方式採用數據結構中的棧實現,具備(LIFO)的順序特色,堆爲一塊一塊的內存

  • 棧因爲其實現方式,在分配速度上比堆快的多。分配一塊棧內存不過是簡單的移動一個指針

  • 在JVM中,棧不會被程序員直接使用,程序員操做的通常都是堆。

  • 棧爲線程私有而堆爲線程共享

雖然堆和棧有這麼多的區別,可是這些區別都是因爲操做系統而決定的,在硬件上,他們本質都是RAM

爲何堆是線程共享的而棧不是?

上面最後一點提到了棧爲線程私有而堆爲線程共享。這是爲何呢???

其實很簡單,爲了解決一個問題:線程間通訊。

想要實現線程間通訊,目前有兩種方法:

  • 消息傳遞
  • 共享內存

共享內存即是咱們所說的將堆設置爲線程間共享的,這樣咱們可以經過堆中的對象實現數據共享,這樣便使得其餘線程可以知道某個線程修改了某個數據。可是這樣帶來的問題可能就有線程安全問題等,可是這樣作的優點便在於速度更快節約內存,Java,C#等使用這種方式

消息傳遞是每一個線程都私有本身的數據空間,當須要線程通訊的時候,便須要一個線程顯示的給另一個線程發送具體的消息,這樣作的可以讓多線程更加安全,可是私有的線程空間和消息傳遞帶來的是須要給內個線程都拷貝相同的對象,變量等,而且可能會帶來效率問題。而Erlang和JoCaml即是使用消息傳遞式線程通訊。

尊重勞動成功,轉載註明原創

參考文章:

Why do threads share the heap space?

What’s the difference between a stack and a heap?

What and where are the stack and heap?


若是以爲寫得不錯,歡迎關注微信公衆號:逸遊Java ,天天不定時發佈一些有關Java進階的文章,感謝關注

相關文章
相關標籤/搜索