最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

阿里的一道Java并發(fā)面試題詳解

 更新時(shí)間:2019年06月20日 09:11:46   作者:匠心零度  
這篇文章主要介紹了阿里的一道Java并發(fā)面試題詳解,網(wǎng)絡(luò)、并發(fā)相關(guān)的知識(shí),相對(duì)其他一些編程知識(shí)點(diǎn)更難一些,主要是不好調(diào)試并且涉及內(nèi)容太多 !,需要的朋友可以參考下

題目

我個(gè)人一直認(rèn)為: 網(wǎng)絡(luò)、并發(fā)相關(guān)的知識(shí),相對(duì)其他一些編程知識(shí)點(diǎn)更難一些,主要是不好調(diào)試并且涉及內(nèi)容太多 !

所以今天就取一篇并發(fā)相關(guān)的內(nèi)容分享下,我相信大家認(rèn)真看完會(huì)有收獲的。

大家可以先看看這個(gè)問(wèn)題,看看這個(gè)是否有問(wèn)題呢? 那里有問(wèn)題呢?

如果你在這個(gè)問(wèn)題上面停留超過(guò)5s的話,那么表示你對(duì)這塊某些知識(shí)還有點(diǎn)模糊,需要再鞏固下,下面我們一起來(lái)分析下!

結(jié)論
多線程并發(fā)的同時(shí)進(jìn)行set、get操作,A線程調(diào)用set方法,B線程并不一定能對(duì)這個(gè)改變可見?。?!

分析
這個(gè)類非常簡(jiǎn)單,里面有一個(gè)屬性,有2個(gè)方法:get、set方法,一個(gè)用來(lái)設(shè)置屬性值,一個(gè)用來(lái)獲取屬性值,在設(shè)置屬性方法上面加了synchronized。

隱式信息: 多線程并發(fā)的同時(shí)進(jìn)行set、get操作,A線程調(diào)用set方法,B線程可以里面感知到嗎???

說(shuō)到這里,問(wèn)題就變成了synchronized在剛剛說(shuō)的上下文下面能否保證可見性?。?!

關(guān)鍵詞synchronized的用法

  • 指定加鎖對(duì)象:對(duì)給定對(duì)象加鎖,進(jìn)入同步代碼前需要獲得給定對(duì)象的鎖。
  • 直接作用于實(shí)例方法:相當(dāng)于對(duì)當(dāng)前實(shí)例加鎖,進(jìn)入同步代碼前要獲得當(dāng)前實(shí)例的鎖。
  • 直接作用于靜態(tài)方法:相當(dāng)于對(duì)當(dāng)前類加鎖,進(jìn)入同步代碼前要獲得當(dāng)前類的鎖。

synchronized它的工作就是對(duì)需要同步的代碼加鎖,使得每一次只有一個(gè)線程可以進(jìn)入同步塊(其實(shí)是一種悲觀策略)從而保證線程之間得安全性。

從這里我們可以知道,我們需要分析的屬于第二類情況,也就是說(shuō)多個(gè)線程如果同時(shí)進(jìn)行set方法的時(shí)候,由于存在鎖,所以會(huì)一個(gè)一個(gè)進(jìn)行set操作,并且是線程安全的,但是get方法并沒有加鎖,表示假如A線程在進(jìn)行set的同時(shí)B線程可以進(jìn)行g(shù)et操作。并且可以多個(gè)線程同時(shí)進(jìn)行g(shù)et操作,但是同一時(shí)間最多只能有一個(gè)set操作。

Java 內(nèi)存模型 happens-before原則

JSR-133 內(nèi)存模型使用 happens-before 的概念來(lái)闡述操作之間的內(nèi)存可見性。在 JMM 中,如果一個(gè)操作執(zhí)行的結(jié)果需要對(duì)另一個(gè)操作可見,那么這兩個(gè)操作之間必須要存在 happens-before 關(guān)系。這里提到的兩個(gè)操作既可以是在一個(gè)線程之內(nèi),也可以是在不同線程之間。

與程序員密切相關(guān)的 happens-before 規(guī)則如下:

  • 程序順序規(guī)則:一個(gè)線程中的每個(gè)操作,happens-before 于該線程中的任意后續(xù)操作。
  • 監(jiān)視器鎖規(guī)則:對(duì)一個(gè)監(jiān)視器的解鎖,happens-before 于隨后對(duì)這個(gè)監(jiān)視器的加鎖。
  • volatile 變量規(guī)則:對(duì)一個(gè) volatile 域的寫,happens-before 于任意后續(xù)對(duì)這個(gè) volatile 域的讀。
  • 傳遞性:如果 A happens-before B,且 B happens-before C,那么 A happens-before C。

注意,兩個(gè)操作之間具有 happens-before 關(guān)系,并不意味著前一個(gè)操作必須要在后一個(gè)操作之前執(zhí)行!happens-before 僅僅要求前一個(gè)操作(執(zhí)行的結(jié)果)對(duì)后一個(gè)操作可見,且前一個(gè)操作按順序排在第二個(gè)操作之前(the first is visible to and ordered before the second)。

其中有監(jiān)視器鎖規(guī)則:對(duì)一個(gè)監(jiān)視器的解鎖,happens-before 于隨后對(duì)這個(gè)監(jiān)視器的加鎖。這一條,僅僅只是針對(duì)synchronized的set方法,而對(duì)于get并沒有這方面的說(shuō)明。

其實(shí)在這種上下文下面一個(gè)synchronized的set方法,一個(gè)普通的get方法,a線程調(diào)用set方法,b線程并不一定能對(duì)這個(gè)改變可見!

volatile

volatile可見性

前面happens-before原則就提到:volatile 變量規(guī)則:對(duì)一個(gè) volatile 域的寫,happens-before 于任意后續(xù)對(duì)這個(gè) volatile 域的讀。 volatile從而保證了多線程下的可見性?。?!

volatile 禁止內(nèi)存重排序

下面是 JMM 針對(duì)編譯器制定的 volatile 重排序規(guī)則表:

為了實(shí)現(xiàn) volatile 的內(nèi)存語(yǔ)義,編譯器在生成字節(jié)碼時(shí),會(huì)在指令序列中插入內(nèi)存屏障來(lái)禁止特定類型的處理器重排序。

下面是基于保守策略的 JMM 內(nèi)存屏障插入策略:

  • 在每個(gè) volatile 寫操作的前面插入一個(gè) StoreStore 屏障。
  • 在每個(gè) volatile 寫操作的后面插入一個(gè) StoreLoad 屏障。
  • 在每個(gè) volatile 讀操作的后面插入一個(gè) LoadLoad 屏障。
  • 在每個(gè) volatile 讀操作的后面插入一個(gè) LoadStore 屏障。

下面是保守策略下,volatile 寫操作 插入內(nèi)存屏障后生成的指令序列示意圖:

下面是在保守策略下,volatile 讀操作 插入內(nèi)存屏障后生成的指令序列示意圖:

上述 volatile 寫操作和 volatile 讀操作的內(nèi)存屏障插入策略非常保守。在實(shí)際執(zhí)行時(shí),只要不改變 volatile 寫-讀的內(nèi)存語(yǔ)義,編譯器可以根據(jù)具體情況省略不必要的屏障。

雙重檢查鎖實(shí)現(xiàn)單例中就需要用到這個(gè)特性!??!

模擬

通過(guò)上面的分析,其實(shí)這個(gè)題目涉及到的內(nèi)容都提到了,并且進(jìn)行了解答。

雖然你知道的原因,但是想模擬并不是一件容易的事情!,下面我們來(lái)模擬看看效果:

public class ThreadSafeCache {
int result;
public int getResult() {
return result;
}
public synchronized void setResult(int result) {
this.result = result;
}
public static void main(String[] args) {
ThreadSafeCache threadSafeCache = new ThreadSafeCache();
for (int i = 0; i < 8; i++) {
new Thread(() -> {
int x = 0;
while (threadSafeCache.getResult() < 100) {
x++;
}
System.out.println(x);
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadSafeCache.setResult(200);
}
}

效果:

程序會(huì)一直卡在這邊不動(dòng),表示set修改的200,get方法并不可見?。?!

添加volatile 關(guān)鍵詞觀察效果

其實(shí)例子中synchronized關(guān)鍵字可以去掉,僅僅用volatile即可。

效果:

代碼很快正常結(jié)束了!

結(jié)論

多線程并發(fā)的同時(shí)進(jìn)行set、get操作,A線程調(diào)用set方法,B線程并不一定能對(duì)這個(gè)改變可見?。。?,上面的代碼中,如果對(duì)get方法也加synchronized也是可見的,還是happens-before的監(jiān)視器鎖規(guī)則:對(duì)一個(gè)監(jiān)視器的解鎖,happens-before 于隨后對(duì)這個(gè)監(jiān)視器的加鎖。只是volatile比synchronized更輕量級(jí),所以本例直接用volatile。但是對(duì)于符合非原子操作i++這里還是不行的還是需要synchronized。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java實(shí)現(xiàn)8種排序算法的示例代碼

    Java實(shí)現(xiàn)8種排序算法的示例代碼

    這篇文章主要介紹了8種JAVA實(shí)現(xiàn)排序算法的示例代碼,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 深入講解SpringBoot Actuator是什么

    深入講解SpringBoot Actuator是什么

    Spring Boot Actuator提供了生產(chǎn)上經(jīng)常用到的功能(如健康檢查,審計(jì),指標(biāo)收集,HTTP跟蹤等),幫助我們監(jiān)控和管理Spring Boot應(yīng)用程序。這些功能都可以通過(guò)JMX或HTTP端點(diǎn)訪問(wèn)
    2023-01-01
  • SpringBoot自動(dòng)配置的實(shí)現(xiàn)原理

    SpringBoot自動(dòng)配置的實(shí)現(xiàn)原理

    這篇文章主要介紹了詳解SpringBoot自動(dòng)配置原理,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • springboot+feign+Hystrix整合(親測(cè)有效)

    springboot+feign+Hystrix整合(親測(cè)有效)

    本文主要介紹了springboot+feign+Hystrix整合,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11
  • IDEA生成標(biāo)準(zhǔn)JavaBean的幾種方法總結(jié)

    IDEA生成標(biāo)準(zhǔn)JavaBean的幾種方法總結(jié)

    標(biāo)準(zhǔn)javaBean是定義一個(gè)類的標(biāo)準(zhǔn)結(jié)構(gòu),下面這篇文章主要給大家總結(jié)介紹了關(guān)于IDEA生成標(biāo)準(zhǔn)JavaBean的幾種方法,文中通過(guò)圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • Elasticsearch聚合查詢概念及字段類型示例

    Elasticsearch聚合查詢概念及字段類型示例

    這篇文章主要為大家介紹了Elasticsearch聚合查詢概念及字段類型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Mybatis增刪改查mapper文件寫法詳解

    Mybatis增刪改查mapper文件寫法詳解

    這篇文章主要介紹了Mybatis增刪改查mapper文件寫法的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Spring?boot?Jpa添加對(duì)象字段使用數(shù)據(jù)庫(kù)默認(rèn)值操作

    Spring?boot?Jpa添加對(duì)象字段使用數(shù)據(jù)庫(kù)默認(rèn)值操作

    這篇文章主要介紹了Spring?boot?Jpa添加對(duì)象字段使用數(shù)據(jù)庫(kù)默認(rèn)值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java如何判斷一個(gè)字符串是否包含某個(gè)字符串

    Java如何判斷一個(gè)字符串是否包含某個(gè)字符串

    這篇文章主要給大家介紹了關(guān)于Java如何判斷一個(gè)字符串是否包含某個(gè)字符串的相關(guān)資料,在實(shí)際編程中,經(jīng)常需要判斷一個(gè)字符串中是否包含某個(gè)子串,需要的朋友可以參考下
    2023-07-07
  • Swagger實(shí)現(xiàn)動(dòng)態(tài)條件注入與全局?jǐn)r截功能詳細(xì)流程

    Swagger實(shí)現(xiàn)動(dòng)態(tài)條件注入與全局?jǐn)r截功能詳細(xì)流程

    這篇文章主要介紹了Swagger實(shí)現(xiàn)動(dòng)態(tài)條件注入與全局?jǐn)r截功能詳細(xì)流程,Swagger 可以提供 API 操作的測(cè)試文檔,本文記錄 Swagger 使用過(guò)程中遇到的小問(wèn)題
    2023-01-01

最新評(píng)論

隆子县| 新沂市| 子洲县| 渭南市| 沭阳县| 墨竹工卡县| 仁寿县| 德惠市| 揭东县| 大连市| 桂阳县| 中西区| 壶关县| 临沭县| 科尔| 和顺县| 阳东县| 丰宁| 泰来县| 皋兰县| 呼图壁县| 玉环县| 易门县| 太白县| 永昌县| 双柏县| 凤冈县| 贵德县| 新龙县| 辰溪县| 宣城市| 来凤县| 高安市| 定远县| 喀喇沁旗| 延寿县| 彰化县| 夏河县| 武威市| 潢川县| 扎兰屯市|