對多線程java內存模型JMM

多線程概念的引入體現了人類從新有效壓力寨計算機。這是很是有必要的,因爲所涉及的讀數據的過程當中的通常操做,如從磁盤、其餘系統、數據庫等,CPU計算速度和數據讀取速度已經嚴重失衡。假設印刷過程當中一個線程將有很是多節點堵塞,使計算效率低下。java

另外,server端是java最擅長的領域,做爲server必須要能同一時候響應多個client的請求,相同須要多線程的支持。在多線程狀況下。高併發將帶來數據的共享與競爭問題。tomcat做爲中間件將多線程併發等細節儘可能封裝起來處理,使用戶對多線程透明,不少其它地關注業務處理就能夠。但假設想要深刻剖析tomcat咱們有必要深刻了解多線程併發技術。此章節將介紹多線程併發的一些底層原理及JDK併發包的實現的相關知識。並不會對所有具體的併發類的用法進行介紹,針對一些在Tomcat中使用的類會略微具體闡述。數據庫

1、Java內存模型——JMM

在多核時代,怎樣提升CPU的性能成爲了一個永恆的話題,而這個話題的討論主要就是怎樣定義一個高性能的內存模型,內存模型用於定義處理器的各層緩存與共享內存的同步機制及線程和內存交互的規則。     緩存

Java的世界也有屬於它本身的內存模型,Java內存模型,即Java Memory Model,簡稱JMM。由於Java被定義成一種跨平臺的語言,因此在內存的描寫敘述上面也要能是跨平臺的。Java虛擬機試圖定義一種統一的內存模型,能將各類底層硬件及操做系統的內存訪問差別進行封裝,使Java程序在不一樣硬件及操做系統上都能達到一樣的併發效果。它描寫敘述了程序中各個變量之間的關係,包含實例域、靜態域、數據元素及在實際計算機系統中將變量存儲到內存和從內存中取出變量的底層細節。tomcat

爲更好理解JMM的工做機制。由圖2-5-1-1帶入。從整體上看有幾個比較重要的主體。主存、工做內存、變量、變量副本、線程等。首先看主存與工做內存及他們的關係,主存保存了java程序的所有變量,固然這個變量不包括局部變量和方法參數,而工做內存則包括了這些變量的副本;其次是線程與工做內存的關係,每個線程都有一個屬於本身的工做內存,不一樣線程之間的工做內存是互相不可見的,且線程對變量的操做也僅僅能是針對本身的工做內存;最後是關於線程之間的通訊機制,由於線程直接不可直接傳遞,假如一條線程對一個變量進行又一次賦值,那麼僅僅能經過例如如下途徑讓另一條線程知道,線程一將變量改變反應到主存中,線程二再從主存中讀取,這樣就基本完畢了線程之間的通訊了。多線程

JMM定義額八個操做來完畢工做內存與主存的通訊。假如一條線程準備對一個變量進行新的賦值操做,它可能會先用lock操做鎖住主存中的某個變量(不讓其它線程得到此變量的鎖。直至使用unlock操做釋放該變量的鎖),接着使用read操做將變量從主存獨到工做內存。緊接着load操做將獲得的變量值放到工做內存中的變量副本,use操做則將變量值傳給線程運行引擎進行運算操做,assign操做把新的變量值從線程運行引擎中傳遞到工做內存,繼續往下,store操做則把變量值從工做內存傳送到主存中,接着write操做將獲得的值寫入主存對應的變量中。最後使用unlock操做釋放變量的鎖。併發

圖2-5-1-1 java內存模型JMM高併發

    Java內存模型具備三個特性:原子性、可見性和有序性。性能

①  原子性,java內存模型保證了read、load、assign、use、store、write六個操做具備原子性。咱們可以以爲除了long和double類型外。對其它基本數據類型所相應的內存單元的訪問讀寫都是原子的。優化

但由於這個原子性的顆粒度過小。一般狀況下咱們需要更大顆粒度的原子性,這時就需要用鎖來保證了。操作系統

②  可見性,在java內存模型中,簡單說假設一條線程更改了共享變量的值,而其它線程能當即知道這個更改。咱們則說這個變量具備可見性。通常來講有四種方式能保證變量的可見性,分別爲volatile、synchronized、final和鎖。首先談談volatile,被此關鍵詞聲明的變量。每當有不論什麼更改時都將當即同步到主存中,而每個線程要使用這個變量時都要又一次從主存刷新到工做內存。這樣就確保了變量的可見性(固然,普通變量終於也會同步到主存,再由主存同步到每個線程的工做內存,僅僅是這個終於可能比較「長久」,不能保證可見性)。由於synchronized底層也是經過鎖進行實現,因此synchronized和鎖的本質是同樣的,當一個線程釋放一個鎖時,將會強制刷新工做內存中的變量值到主存中,而當還有一個線程獲取此鎖的時候將會強制又一次裝載此變量值。固然這兩個線程獲取的是同一個鎖。這樣就保證了變量的可見性。被final聲明的變量一旦完畢初始化,其它線程就能看到這個final變量。事實上,可見性事實上可以當作是一種機制,線程在進入/退出同步塊程序時,它將發送/接收一個變量的更改。

③  有序性。有序性指在線程內看方法的運行,所有的指令都是有序的。都依照一種串行方式運行。而在線程內觀察其它線程,所有指令都是無序的,指令均可能交叉運行。Java中提供了volatile和synchronized兩個關鍵詞保證線程之間操做的有序性。而這個有序性不過相對的,volatile禁止指令重排序,synchronized則保證持有同一個鎖的同步塊只能串行運行。

JMM可以說是Java的基礎。它的定義將直接影響JVM及java多線程實現的機制,要想深刻了解多線程問題相關的現象。正確Java內存模型的深刻研究是必不可少的。

它的定義必須考慮到如下幾個方面,一個是,如何更有效地提升該線程的性能效率。二是如何在底層物理硬件和操做系統的差別,提供統一的對外屏蔽的概念;最後,它是多麼的嚴謹和輕鬆的典範。語義確保不會產生歧義和一些優化擴展。

相關文章
相關標籤/搜索