淺談Java併發編程系列(四)—— 原子性、可見性與有序性

Java內存模型是圍繞着在併發過程當中如何處理原子性、可見性和有序性這3個特徵來創建的,咱們來看下哪些操做實現了這3個特性。多線程

原子性(atomicity): 由Java內存模型來直接保證原子性變量操做包括read, load, assign, use, store和write。大體能夠認爲基本數據類型的訪問讀寫是具備原子性的。若是應用場景須要一個更大範圍的原子性保證,Java內存模型還提供了lock和unlock操做來知足需求,儘管虛擬機沒有把lock和unlock操做直接開放給用戶使用,可是卻提供了更高層次的字節碼指令monitorenter和monitorexit來隱式地使用這兩個操做,這兩個字節碼指令反映到Java代碼中就是同步塊——synchronized關鍵字,所以在synchronized塊之間的操做也具有原子性。併發

可見性(visibility): 可見性是指當一個線程修改了共享變量的值,其餘線程可以當即得知這個修改。Java內存模型是經過在變量修改後將新值同步到主內存,不管是普通變量仍是volatile變量都是如此,普通變量與volatile變量的區別是,volatile的特殊規則保證了新值能當即同步到主內存,以及每次使用前當即從主內存刷新。所以,能夠說volatile保證了多線程操做時變量的可見性,而普通變量不能保證這一點。this

除了volatile以外,Java還有兩個關鍵字能實現可見性,即synchronized和final。同步塊的可見性是由「對一個變量執行unlock操做以前,必須先把此變量同步回主內存中」這條規則得到的,而final關鍵字的可見性是指:被final修飾的字段在構造器中一旦初始化完成,而且構造器沒有把"this"的引用傳遞出去(this引用逃逸是一件很危險的事情,其餘線程有可能經過這個引用訪問到「初始化了一半」的對象),那在其餘線程中就能看見final字段的值。atom

有序性: Java程序自然的有序性能夠總結爲一句話:若是本線程內觀察,全部的操做都是有序的;若是在一個線程中觀察另外一個線程,全部的操做都是無序的。前半句是指「線程內表現爲串行的語義」,後半句是指「指令重排序」現象和「工做內存與主內存同步延遲」現象。線程

Java語言提供了volatile和synchronized兩個關鍵字來保證線程之間操做的有序性,volatile關鍵字自己就包含了禁止指令重排序的語義,而synchronized則是由「一個變量在同一時刻只容許一條線程對其進行lock操做」這條規則得到的,這條規則決定了持有同一個鎖的兩個同步塊只能串行地進入。對象

相關文章
相關標籤/搜索