爲什麼synchronized無法禁止指令重排,卻能保證有序性?

轉發:https://www.toutiao.com/i6795075486847336963/

爲什麼synchronized無法禁止指令重排,卻能保證有序性?

據說這位讀者前面的很多問題會的都還可以,屬於那種可過可不過的類型的,面試官出了最後一道題,就是回答的滿意就可以給Offer,回答的不好就不讓過的意思。

那麼這道題到底應該如何回答呢?

首先我們要分析下這道題,不得不說這個面試官還是有一定的水平的,這簡單的一個問題,其實裏面還是包含了很多信息的,要想回答好這個問題,面試者至少要知道一下概念:

Java內存模型、併發編程有序性問題、指令重排、synchronized鎖、可重入鎖、排它鎖、as-if-serial語義、單線程&多線程

所以,這道題的正確回答姿勢是怎樣的呢?

標準答案如下:

這是個好問題,這個問題我曾經也思考過,也查閱過很多資料,甚至還去看過hotsopt的源碼。

  • 不管三七二十一,上來先舔一波,然後表示下自己求知好學的態度。

爲了進一步提升計算機各方面能力,在硬件層面做了很多優化,如處理器優化和指令重排等,但是這些技術的引入就會導致有序性問題。

  • 先告訴面試官你知道什麼是有序性問題,也知道是什麼原因導致的有序性問題

我們也知道,最好的解決有序性問題的辦法,就是禁止處理器優化和指令重排,就像volatile中使用內存屏障一樣。

  • 表明你知道啥是指令重排,也知道他的實現原理

但是,雖然很多硬件都會爲了優化做一些重排,但是在Java中,不管怎麼排序,都不能影響單線程程序的執行結果。這就是as-if-serial語義,所有硬件優化的前提都是必須遵守as-if-serial語義。

  • 重點!解釋下什麼是as-if-serial語義,因爲這是這道題的第一個關鍵詞,答上來就對了一半了

再說下synchronized,他是Java提供的鎖,可以通過他對Java中的對象加鎖,並且他是一種排他的、可重入的鎖。

  • 裝X項,不留痕跡的展示自己對鎖瞭解的比較多

所以,當某個線程執行到一段被synchronized修飾的代碼之前,會先進行加鎖,執行完之後再進行解鎖。在加鎖之後,解鎖之前,其他線程是無法再次獲得鎖的,只有這條加鎖線程可以重複獲得該鎖。

  • 介紹synchronized的原理,這是本題的第二個關鍵點,到這裏基本就可以拿滿分了。

synchronized通過排他鎖的方式就保證了同一時間內,被synchronized修飾的代碼是單線程執行的。所以呢,這就滿足了as-if-serial語義的一個關鍵前提,那就是單線程,因爲有as-if-serial語義保證,單線程的有序性就天然存在了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章