1、從操做系統角度理解程序、進程、線程
1.1 強烈推薦兩篇博文,闡述的是Linux的程序、進程、線程的內存使用
Linux從程序到進程:www.cnblogs.com/vamei/archi…html
Linux併發與同步:www.cnblogs.com/vamei/archi…緩存
1.2 下圖是Java中多線程在內存中的分佈。建議先看上面兩篇文章,寫的很好因此直接推薦。
Heap(堆)是一個進程中的全部線程共享的,用於存儲動態變量;每建立一個線程,就會給這個線程分配一個棧,Thread棧是線程獨有的,一個線程沒法訪問其餘線程棧(局部變量存儲在棧中)。
1.3 下圖爲Java的堆和棧中的對象存儲位置
2、多線程原子性問題和內存可見性問題
2.1 Java內存模型與硬件模型
2.2 原子性問題和可見性問題
內存可見性問題,從2.1中的內存模型與硬件模型可知,每一個CPU都有本身的寄存器(CPU Registers)以及緩存(CPU Cache Memmory),線程的運行硬件是CPU,一個線程操做主內存的數據時,先從主內存中讀取數據,CPU進行運算,可是運算結束後,有可能並不會將數據存入主內存(RAM-Main Memory),這樣其餘線程降沒法看到數據的變化,這就致使了內存可見性問題。
原子性問題,如圖中的Race Condition那張圖,count是一個共享的可變變量,左邊的線程和右邊的線程對count的操做都是count+1,這個操做分爲三個步驟:讀取count的值→count+1→存儲count。左線程在讀取了count的值爲1後,正在作count+1時,右線程讀取的count值仍然爲1,右線程也作了count+1,但也是1+1,這樣當兩個線程作完三個步驟後,count是2並非3,這樣就引入了原子性問題。這樣的三個步驟應該以原子的方式進行(即在這三個步驟運行過程當中,不能有其餘操做),這樣的操做也叫
複合操做。