面試題之併發相關專欄五

一、請談談volatile有什麼特點,爲什麼它能保證變量對所有線程的可見性?

當一個變量被volatile修飾後,具備兩個特性:

  • 保證此變量對所有線程的可見性,當一條線程修改了這個變量的值,新值對於其他線程是可以立即得知的,而普通變量做不到這一點。
  • 禁止指令重排序優化,普通變量僅僅能保證在方法執行過程中,得到正確結果,但是不保證程序代碼的執行順序。

內存模型定義了8種內存間操作來保證可見性:

  •     lock/unlock
  •     read/write
  •     load/store
  •     use/assgin

二、volatile能保證線程間的變量可見性,是不是就意味着基於volatile變量的運算就是併發安全的?

這很顯然並不是的。基於volatile變量的運算在併發下不一定是線程安全的,volatile變量 在各個線程的工作內存,不存在一致性問題(各個線程的工作內存中volatile變量,每次使用前都要刷新到主內存),但是java裏面的運算並不是原子操作,導致volatile變量的運算在併發下也不一定就是線程安全的。volatile只保證了可見性,並不能保證原子性。

三、請對比下volatile和Synchronized的異同?

  • Synchronized既保證了可見性,又保證了原子性,而volatile只能保證可見性,不能保證原子性;
  • volatile僅能使用在變量級別;Synchronized則可以使用在變量、方法、和類級別的;
  • volatile本質是在告訴JVM當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取;Synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住;
  • volatile不會造成線程的阻塞;Synchronized可能會造成線程的阻塞;
  • volatile標記的變量不會被編譯器優化;Synchronized標記的變量可以被編譯器優化;

四、請談談ThreadLocal是怎麼解決併發安全的?

 ThreadLocal是Java提供的一種保存線程私有信息的機制,因爲其在整個線程生命週期內有效,所以可以方便地在一個線程關聯的不同業務模塊之間傳遞信息,比如事務ID、Cookie等上下文信息。 ThreadLocal爲每一個線程維護變量的副本,把共享數據的可見範圍限制到同一個線程之內,其實現原理是,在 ThreadLocal類中有一個Map,用於存儲每個線程的變量副本。

五、談談你對ThreadLocal的理解,使用ThreadLocal需要注意些什麼?

  • ThreadLocal 變量解決了多線程環境下單個線程中變量的共享問題,使用名爲ThreadLocalMap的哈希表進行維護(key爲ThreadLocal變量名,value爲ThreadLocal變量的值);
  • 設想如果將一個大對象放入ThreadLocal 中,並且還沒有remove。那麼就可能會造成OutOfMemoryError,如果不會造成OutOfMemoryError那麼也會浪費Java堆內存。使用時需要注意以下幾點:
  1.     線程之間的threadLocal變量是互不影響的;
  2.     使用private final static進行修飾,防止多實例時內存的泄露問題;
  3.     線程池環境下使用後將threadLocal變量remove掉或設置成一個初始值;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章