日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

JMM和happens-before原则

發(fā)布時(shí)間:2025/3/19 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JMM和happens-before原则 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

vJMM:

  Java Memory Model(Java內(nèi)存模型),圍繞著在并發(fā)過(guò)程中如何處理可見(jiàn)性原子性有序性這三個(gè)特性而建立的模型。

v可見(jiàn)性:

  JMM提供了volatile變量定義、final、synchronized塊來(lái)保證可見(jiàn)性。
例如:線程a在將共享變量x=1寫(xiě)入主內(nèi)存的時(shí)候,如何保證線程b讀取共享變量x的值為1,這就是JMM做的事情。JMM通過(guò)控制主內(nèi)存與每個(gè)線程的本地內(nèi)存之間的交互,來(lái)為java程序員提供內(nèi)存可見(jiàn)性保證。

v原子性:

  JMM提供保證了訪問(wèn)基本數(shù)據(jù)類(lèi)型的原子性(其實(shí)在寫(xiě)一個(gè)工作內(nèi)存變量到主內(nèi)存是分主要兩步:store、write),但是實(shí)際業(yè)務(wù)處理場(chǎng)景往往是需要更大的范圍的原子性保證,所以模型也提供了synchronized塊來(lái)保證。

v有序性:

  這個(gè)概念是相對(duì)而言的,如果在本線程內(nèi),所有的操作都是有序的,如果在一個(gè)線程觀察另一個(gè)線程,所有的操作都是無(wú)序的,前句是“線程內(nèi)表現(xiàn)為串行行為”,后句是“指令的重排序”和“工作內(nèi)存和主內(nèi)存同步延遲”現(xiàn)象,模型提供了volatile和synchronized來(lái)保證線程之間操作的有序性

v重排序:

  在執(zhí)行程序時(shí)為了提高性能,編譯器和處理器常常會(huì)對(duì)指令做重排序(編譯器、處理器),就是因?yàn)檫@些重排序,所以可能會(huì)導(dǎo)致多線程程序出現(xiàn)內(nèi)存可見(jiàn)性問(wèn)題(數(shù)據(jù)安全問(wèn)題)和有序性問(wèn)題。
JMM是如何處理的呢?
對(duì)于編譯器,JMM的編譯器重排序規(guī)則會(huì)禁止特定類(lèi)型的編譯器重排序
對(duì)于處理器重排序,JMM的處理器重排序規(guī)則會(huì)要求java編譯器在生成指令序列時(shí),插入特定類(lèi)型的內(nèi)存屏障(memory barriers,intel稱(chēng)之為memory fence)指令,通過(guò)內(nèi)存屏障指令來(lái)禁止特定類(lèi)型的處理器重排序
總之一句話,JMM是通過(guò)禁止特定類(lèi)型的編譯器重排序和處理器重排序來(lái)為程序員提供一致的內(nèi)存可見(jiàn)性保證。

A線程具體什么時(shí)候刷新共享數(shù)據(jù)到主內(nèi)存是不確定的,假設(shè)我們使用了同步原語(yǔ)(synchronized,volatile和final),那么刷新的時(shí)間是確定的,例如:線程A釋放鎖后會(huì)同步到主內(nèi)存,線程B獲取鎖后會(huì)同步主內(nèi)存數(shù)據(jù),即“A線程釋放鎖--B線程獲取鎖”可以實(shí)現(xiàn)A,B線程之間的通信。

?

vjava中volatile關(guān)鍵字的含義

  http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html

vJava內(nèi)存模型happens-before法則

  The rules for happens-before are:?
Program order rule. Each action in a thread happens-before every action in that thread that comes later in the program order.?
Monitor lock rule. An unlock on a monitor lock happens-before every subsequent lock on that same monitor lock.?
Volatile variable rule. A write to a volatile field happens-before every subsequent read of that same field.?
Thread start rule. A call to Thread.start on a thread happens-before every action in the started thread.?
Thread termination rule. Any action in a thread happens-before any other thread detects that thread has terminated, either by successfully return from   Thread.join or by Thread.isAlive returning false.?
Interruption rule. A thread calling interrupt on another thread happens-before the interrupted thread detects the interrupt (either by having   InterruptedException tHRown, or invoking isInterrupted or interrupted).?
Finalizer rule. The end of a constructor for an object happens-before the start of the finalizer for that object.?
Transitivity. If A happens-before B, and B happens-before C, then A happens-before C.?
----------------------------

v什么是happens-before?

  happens-before就是“什么什么一定在什么什么之前運(yùn)行”,也就是保證順序性。?
因?yàn)镃PU是可以不按我們寫(xiě)代碼的順序執(zhí)行內(nèi)存的存取過(guò)程的,也就是指令會(huì)亂序或并行運(yùn)行,?
只有上面的happens-before所規(guī)定的情況下,才保證順序性。

v為什么存在可見(jiàn)性問(wèn)題?

  簡(jiǎn)單介紹下。相對(duì)于內(nèi)存,CPU的速度是極高的,如果CPU需要存取數(shù)據(jù)時(shí)都直接與內(nèi)存打交道,在存取過(guò)程中,CPU將一直空閑,這是一種極大的浪費(fèi),媽媽說(shuō),浪費(fèi)是不好的,所以,現(xiàn)代的CPU里都有很多寄存器,多級(jí)cache,他們比內(nèi)存的存取速度高多了。某個(gè)線程執(zhí)行時(shí),內(nèi)存中的一份數(shù)據(jù),會(huì)存在于該線程的工作存儲(chǔ)中(working memory,是cache和寄存器的一個(gè)抽象,這個(gè)解釋源于《Concurrent Programming in Java: Design Principles and Patterns, Second Edition》§2.2.7,原文:Every thread is defined to have a working memory (an abstraction of caches and registers) in which to store values. 有不少人覺(jué)得working memory是內(nèi)存的某個(gè)部分,這可能是有些譯作將working memory譯為工作內(nèi)存的緣故,為避免混淆,這里稱(chēng)其為工作存儲(chǔ),每個(gè)線程都有自己的工作存儲(chǔ)),并在某個(gè)特定時(shí)候回寫(xiě)到內(nèi)存。單線程時(shí),這沒(méi)有問(wèn)題,如果是多線程要同時(shí)訪問(wèn)同一個(gè)變量呢?內(nèi)存中一個(gè)變量會(huì)存在于多個(gè)工作存儲(chǔ)中,線程1修改了變量a的值什么時(shí)候?qū)€程2可見(jiàn)?此外,編譯器或運(yùn)行時(shí)為了效率可以在允許的時(shí)候?qū)χ噶钸M(jìn)行重排序,重排序后的執(zhí)行順序就與代碼不一致了,這樣線程2讀取某個(gè)變量的時(shí)候線程1可能還沒(méi)有進(jìn)行寫(xiě)入操作呢,雖然代碼順序上寫(xiě)操作是在前面的。這就是可見(jiàn)性問(wèn)題的由來(lái)。

  并且,多個(gè)CPU之間的緩存也不保證實(shí)時(shí)同步,?
也就是說(shuō)你剛給一個(gè)變量賦值,另一個(gè)線程立即獲取它的值,可能拿到的卻是舊值(或null),?
因?yàn)閮蓚€(gè)線程在不同的CPU執(zhí)行,它們看到的緩存值不一樣,?
只有在synchronized或volatile或final的性況下才能保證正確性,?
很多人用synchronized時(shí)只記得有l(wèi)ock的功能,而忘記了線程間的可見(jiàn)性問(wèn)題。?

public class Test {private int n;public void set(int n) {this.n = n;}public void check() {if (n != n)throw new Exception("check Error!");} }

  check()中的 n != n 好像永遠(yuǎn)不會(huì)成立,因?yàn)樗麄冎赶蛲粋€(gè)值,但非同步時(shí)卻很有可能發(fā)生。?

另外,JMM不保證創(chuàng)建過(guò)程的原子性,讀寫(xiě)并發(fā)時(shí),可能看到不完整的對(duì)象,?
這也是為什么單例模式中著名的"雙重檢查成例"方法,在Java中行不通。(但.Net的內(nèi)存模型保證這一點(diǎn))?
當(dāng)然,在Java中單例的延遲加載可以用另一種方案實(shí)現(xiàn)(方案四):?

v方案一:非延遲加載單例類(lèi)?

public class Singleton {private Singleton(){}private static final Singleton instance = new Singleton();public static Singleton getInstance() {return instance;   } }

v方案二:簡(jiǎn)單的同步延遲加載?

public class Singleton { private static Singleton instance = null;public static synchronized Singleton getInstance() {if (instance == null)instance = new Singleton();return instance;   } }

v方案三:雙重檢查成例延遲加載?

  目的是避開(kāi)過(guò)多的同步,?
但在Java中行不通,因?yàn)橥綁K外面的if (instance == null)可能看到已存在,但不完整的實(shí)例。?
JDK5.0以后版本若instance為volatile則可行?

  用volatile修飾的變量,線程在每次使用變量的時(shí)候,都會(huì)讀取變量修改后的最新的值。volatile很容易被誤用,用來(lái)進(jìn)行原子性操作。

public class Singleton { private static Singleton instance = null;public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;   } }

v方案四:類(lèi)加載器延遲加載?

public class Singleton { private static class Holder {static final Singleton instance = new Singleton();}public static Singleton getInstance() {return Holder.instance;   } }








本文轉(zhuǎn)自 小眼兒 博客園博客,原文鏈接:http://www.cnblogs.com/hujunzheng/p/5118256.html,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者

總結(jié)

以上是生活随笔為你收集整理的JMM和happens-before原则的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。