鍍金池/ 教程/ Java/ 實現(xiàn)內(nèi)存可見性的兩種方法比較:synchronized 和 Volatile
并發(fā)新特性—信號量 Semaphore
線程間協(xié)作:wait、notify、notifyAll
notify 通知的遺漏
notifyAll 造成的早期通知問題
多線程的實現(xiàn)方法
深入 Java 內(nèi)存模型(1)
多線程環(huán)境下安全使用集合 API
并發(fā)新特性—Lock 鎖與條件變量
生產(chǎn)者—消費者模型
深入 Java 內(nèi)存模型(2)
線程中斷
Volatile 關(guān)鍵字(上)
并發(fā)新特性—阻塞隊列與阻塞棧
可重入內(nèi)置鎖
守護線程與線程阻塞
并發(fā)新特性—障礙器 CyclicBarrier
Volatile 關(guān)鍵字(下)
synchronized 關(guān)鍵字
synchronized 的另個一重要作用:內(nèi)存可見性
并發(fā)新特性—Executor 框架與線程池
并發(fā)性與多線程介紹
死鎖
實現(xiàn)內(nèi)存可見性的兩種方法比較:synchronized 和 Volatile
線程掛起、恢復(fù)與終止

實現(xiàn)內(nèi)存可見性的兩種方法比較:synchronized 和 Volatile

在《synchronized 的另個一重要作用:內(nèi)存可見性》這篇文中,講述了通過同步實現(xiàn)內(nèi)存可見性的方法,在《Volatile 關(guān)鍵字(上)》這篇文中,講述了通過 volatile 變量實現(xiàn)內(nèi)存可見性的方法,這里比較下二者的區(qū)別。

  • volatile 變量是一種稍弱的同步機制在訪問 volatile 變量時不會執(zhí)行加鎖操作,因此也就不會使執(zhí)行線程阻塞,因此 volatile 變量是一種比 synchronized 關(guān)鍵字更輕量級的同步機制。
  • 從內(nèi)存可見性的角度看,寫入 volatile 變量相當(dāng)于退出同步代碼塊,而讀取 volatile 變量相當(dāng)于進入同步代碼塊。
  • 在代碼中如果過度依賴 volatile 變量來控制狀態(tài)的可見性,通常會比使用鎖的代碼更脆弱,也更難以理解。僅當(dāng) volatile 變量能簡化代碼的實現(xiàn)以及對同步策略的驗證時,才應(yīng)該使用它。一般來說,用同步機制會更安全些。
  • 加鎖機制(即同步機制)既可以確??梢娦杂挚梢源_保原子性,而 volatile 變量只能確??梢娦?,原因是聲明為 volatile 的簡單變量如果當(dāng)前值與該變量以前的值相關(guān),那么 volatile 關(guān)鍵字不起作用,也就是說如下的表達式都不是原子操作:count++、count = count+1。

當(dāng)且僅當(dāng)滿足以下所有條件時,才應(yīng)該使用 volatile 變量:

  • 對變量的寫入操作不依賴變量的當(dāng)前值,或者你能確保只有單個線程更新變量的值。
  • 該變量沒有包含在具有其他變量的不變式中。

總結(jié):在需要同步的時候,第一選擇應(yīng)該是 synchronized 關(guān)鍵字,這是最安全的方式,嘗試其他任何方式都是有風(fēng)險的。尤其在、jdK1.5 之后,對 synchronized 同步機制做了很多優(yōu)化,如:自適應(yīng)的自旋鎖、鎖粗化、鎖消除、輕量級鎖等,使得它的性能明顯有了很大的提升。