JSR133—Java Memory Model

JSR:https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html
很早的譯文:http://snake1987.iteye.com/blog/983254

What is a memory model, anyway?

  • 在處理器的層次,一個(gè)存儲(chǔ)模型定義必要的并且足夠的條件,讓當(dāng)前的處理器可以看到另外的處理器寫進(jìn)一個(gè)儲(chǔ)存(memory,如一個(gè)變量),并且當(dāng)前的處理器的寫進(jìn)memory能被別的處理器看到。一些處理器展示了一個(gè)強(qiáng)壯(Strong)的存儲(chǔ)模型,他可以讓所有的處理器看到儲(chǔ)存在一個(gè)memory的正確的相同的值。其他的處理器展示了一個(gè)較弱的存儲(chǔ)模型,它提供一些特殊的指令,叫做存儲(chǔ)屏障,這些指令可以flush或者invalidate這個(gè)本地寄存器的高速緩存,以便可以看到別的寄存器的寫memory操作和讓本寄存器的寫memory被別的寄存器看到。當(dāng)執(zhí)行l(wèi)ock或者unlock動(dòng)作的時(shí)候,這些存儲(chǔ)屏障通常會(huì)表現(xiàn)出來(lái),他們?cè)谝粋€(gè)高層語(yǔ)言是對(duì)編程人員是不可見的
  • 有時(shí),用強(qiáng)?。⊿trong)的存儲(chǔ)模型寫程序更加容易,因?yàn)榭梢詼p少存儲(chǔ)屏障的試用。然而,即使是一些最強(qiáng)健的存儲(chǔ)模型,存儲(chǔ)屏障經(jīng)常也是有必要的:quite frequently their placement is counterintuitive?,F(xiàn)代的趨勢(shì)是,處理器的設(shè)計(jì)上,較弱的內(nèi)存模型更被支持,因?yàn)樗麄兙徍土烁咚倬彺娴囊恢滦詥?wèn)題,允許了更大的吞吐率通過(guò)多處理器和大容量?jī)?nèi)存。

Do other languages, like C++, have a memory model?

  • 大部分其他的程序語(yǔ)言,像c和c++,都不是設(shè)計(jì)為直接支持多線程的。這些語(yǔ)言提供的保護(hù)抵抗(against)一些種類的reorderings:像發(fā)生在編譯器的和結(jié)構(gòu)的reorder,是嚴(yán)重依賴由threading libraries(像pthreads)的使用提供的保障(沒(méi)翻譯好~),和編譯器使用,和平臺(tái)代碼運(yùn)行

What is JSR 133 about?

  • 自從1997年以來(lái),一些關(guān)于jmm的嚴(yán)重的缺陷(像定義在Java Language Specification chapter 17的)已經(jīng)被發(fā)現(xiàn)。這些缺陷允許一些迷惑的舉止(像final fields被觀察到改變了他們的值)和破壞編譯器表現(xiàn)一些通常的優(yōu)化措施的能力
  • Jmm是一個(gè)有野心的承諾(ambitious undertaking)。這是第一次一個(gè)程序語(yǔ)言定義嘗試去包含一個(gè)存儲(chǔ)模型,這個(gè)存儲(chǔ)模型可以為穿過(guò)一系列結(jié)構(gòu)的并發(fā)提供一致的語(yǔ)意。很不幸,定義一個(gè)一致的和直覺(jué)的(intuitive)存儲(chǔ)模型被證明是比想象中還要困難。JSR133為java語(yǔ)言定義了一個(gè)新的存儲(chǔ)模型,修復(fù)了早期存儲(chǔ)模型的缺陷。為了做到這點(diǎn),final和volatile的語(yǔ)義將被改變。

JSR133的目標(biāo)包括:

  • 保留已存在的安全保證,像type-safety,并且強(qiáng)化其他的。舉個(gè)例子,變量的值不是憑空創(chuàng)造的:線程觀察到的每個(gè)變量的值必須是某個(gè)線程有原因地設(shè)置的
  • 關(guān)于synchronized程序的的正確的語(yǔ)義應(yīng)該盡可能地簡(jiǎn)單和intuitive
  • 不完整,不正確的synchronized程序的語(yǔ)義應(yīng)該被定義,這樣能夠讓潛在的安全隱患最小化
  • 編程人員對(duì)于多線程程序與內(nèi)存的交互應(yīng)該要有有原因的信心。(也就是說(shuō)不能盲目的自信這個(gè)代碼是正確的)
  • 正確地設(shè)計(jì)高性能的jvm實(shí)現(xiàn),并且能跨越大范圍的流行硬件結(jié)構(gòu)是有可能的
  • 一個(gè)新的保障initialization safety應(yīng)該被提供。如果一個(gè)對(duì)象被合適的constructed(這就意味著該對(duì)象的引用在構(gòu)造(construction)期間沒(méi)有逃逸escape),這樣所有看到該對(duì)象的引用的線程也能看到他的設(shè)置在構(gòu)造函數(shù)中的final域的值,而不需要synchronization。
    A new guarantee of initialization safety should be provided. If an object is properly constructed (which means that references to it do not escape during construction), then all threads which see a reference to that object will also see the values for its final fields that were set in the constructor, without the need for synchronization.
  • 要將對(duì)已有代碼的影響最小化

What is meant by reordering?

  • 有很多的例子:訪問(wèn)一個(gè)程序變量(object instance fields,class static fields,and array elements)時(shí)可能碰到被以不同的順序執(zhí)行,而不是被定義在程序中的順序。編譯器是允許以優(yōu)化的名義來(lái)改變指令的順序的。處理器可能在一個(gè)確切的環(huán)境中執(zhí)行改變了順序的指令。數(shù)據(jù)可能在寄存器,處理器告訴緩存,和主存之間以不同的順序移動(dòng),而不是定義在程序中的順序。
  • 舉個(gè)例子,如果一個(gè)線程寫一個(gè)field a,并且然后寫一個(gè)field b,并且b的值不依賴于a的值,這樣編譯器是允許去重新排序這些操作的,并且告訴緩存也是允許去flush b的值在a之前到主存上。有一系列潛在的重排序的原因,像編譯器,JIT,和高速緩存。
  • 編譯器,runtime和硬件是提供一個(gè)協(xié)作去創(chuàng)建一個(gè)“似乎是順序的”的語(yǔ)義的幻想的,這就意味著,在一個(gè)單線程的程序,程序應(yīng)該不能觀察到重排序。然而,重排序會(huì)出現(xiàn)在不正確的synchronized多線程程序,在那里一個(gè)線程是能觀察到別的線程的影響的,并且能夠檢測(cè)到變量的訪問(wèn)對(duì)其他的線程變得可見,在一個(gè)不同的順序,而不是定義在程序中的順序。
    大部分的時(shí)間,一個(gè)線程不關(guān)心其他的線程正在做什么。如果需要關(guān)心了,那就需要synchronization了

Synchronization做了什么?

  • Synchronization有很多方面的內(nèi)容,最被廣泛知道的一個(gè)是互斥:一次只有一個(gè)線程可以持有監(jiān)視器(monitor),這樣,這就意味著一次一個(gè)線程進(jìn)入了一個(gè)由一個(gè)monitor監(jiān)控的synchronized塊,其他的線程不能進(jìn)入這個(gè)代碼塊中,直到第一個(gè)線程退出

  • 但是除了互斥之外,synchronization還有更多的內(nèi)容。Synchronization保證了一個(gè)線程的發(fā)生在同步塊之中或者之前的memory寫,可以被其他synchronize在同樣的monitor的線程看到。在我們退出了一個(gè)synchronized塊,我們釋放monitor,這樣會(huì)flushing高速緩存到主存,這樣,這個(gè)線程的寫memory對(duì)其他線程而言就是可見的。我們能夠進(jìn)入同步塊之前,我們需要獲得monitor,這個(gè)操作會(huì)讓本地處理器的高速緩存變得無(wú)效,這樣變量將會(huì)從主存中重新加載。我們?nèi)缓缶湍軌蚩吹街暗尼尫胖械乃械膍emory寫。
    討論到高速緩存相關(guān)聯(lián)的,聽起來(lái)像這些事件只會(huì)影響多處理器的機(jī)器。然而,重排序的影響在但處理器機(jī)器也很容易被看見。舉個(gè)例子:編譯器移動(dòng)你的代碼在到一個(gè)acquire之前或者一個(gè)release之后是不可能的。當(dāng)我們說(shuō)acquires和releases在高速緩存起作用,我們是使用了一個(gè)數(shù)字的可能結(jié)果的速記法(這段不知道啥意思~~)
    新的存儲(chǔ)模型語(yǔ)義創(chuàng)造了一個(gè)偏序的內(nèi)存操作(讀field,寫field,lock,unlock)和其他線程操作(start和join)。在那里我們說(shuō)一些動(dòng)作happen-before其他的操作。當(dāng)一個(gè)操作happen-before,首先保證了第二個(gè)操作對(duì)第一個(gè)操作是可見的。這些順序的規(guī)則在以下:

  • Each action in a thread happens before every action in that thread that comes later in the program's order.

  • An unlock on a monitor happens before every subsequent lock on that same monitor.

  • A write to a volatile field happens before every subsequent read of that same volatile.

  • A call to start() on a thread happens before any actions in the started thread.

  • All actions in a thread happen before any other thread successfully returns from a join() on that thread.

這意味著一個(gè)線程的任何存儲(chǔ)操作對(duì)于任何線程,在他進(jìn)入一個(gè)被同一個(gè)monitor保護(hù)同步塊之后并且在退出同步塊之前是可見的,因?yàn)樗械拇鎯?chǔ)操作happen before這個(gè)release,并且release happen before這個(gè)acquire。
另一個(gè)暗示是:下面的代碼是不可用的
synchronized (new Object()) {}
This is actually a no-op,并且你的編譯器可以將他完全一出,因?yàn)榫幾g器知道不可能有其他的線程會(huì)synchronize在這個(gè)monitor。你不得不為一個(gè)想要看到另一個(gè)線程結(jié)果的線程建立一個(gè)happens before關(guān)系

注意:如果需要一個(gè)合適的happen-before關(guān)系,所有的線程synchronize在同一個(gè)monitor是很重要的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • http://tutorials.jenkov.com/java-concurrency/java-memory-...
    遠(yuǎn)o_O閱讀 936評(píng)論 0 1
  • What is a memory model? What is the JMM? What does synchr...
    一顆北上廣的心閱讀 793評(píng)論 0 51
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,872評(píng)論 11 349
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,688評(píng)論 19 139
  • 人生有兩種境界:一種痛而不言,另一種笑而不語(yǔ)。 不知從何時(shí)起,自己越來(lái)越沉默。 每每被人問(wèn)起一些事例如知識(shí)點(diǎn)、八卦...
    喵先森123閱讀 281評(píng)論 0 0

友情鏈接更多精彩內(nèi)容