synchronized和Lock都是悲觀鎖,它們認爲當使用數據的時候必定有其它線程來修改,因此在獲取數據的時候就會加鎖,確保不會被其它線程修改。數據庫
synchronized代碼塊:微信
public synchronized void update() { //同步資源 }
Lock代碼塊:多線程
public void update() { Lock lock = new ReentrantLock(); lock.lock(); try { //同步資源 } finally { lock.unlock(); } }
樂觀鎖,它認爲使用數據的時候不會有別的線程來修改數據,因此不會加鎖。只要在自身要進行update操做的時候,纔會去判斷以前的數據是否被別的線程修改了。若是沒有被修改則會修改爲功,相反則會修改不成功。這裏最典型的是java.util.concurrent併發包中的遞增操做就經過CAS自旋實現的。併發
CAS代碼塊app
public class TestLock { AtomicInteger atomicInteger = new AtomicInteger(0); public int add() { return atomicInteger.incrementAndGet(); }}
什麼是CAS,CAS的全稱爲Compare And Swap(比較與交換),是一種無鎖算法。在不使用鎖(沒有線程被阻塞)的狀況下實現多線程之間的變量同步。性能
總結: 這裏咱們能夠得出悲觀鎖適合寫操做多的場景,先加鎖能夠保證寫操做時數據正確。樂觀鎖適合讀操做多的場景,不加鎖的特色可以使其讀操做的性能大幅提高。不過從jdk1.8以後java已經對synchronized作了優化,性能上有了大幅度的提高。可是樂觀鎖CAS,也不是那麼十全十美,目前它存在三個三大問題。大數據
ABA問題(JDK1.5以後已有解決方案):CAS須要在操做值的時候檢查內存值是否發生變化,沒有發生變化纔會更新內存值。可是若是內存值原來是A,後來變成了B,而後又變成了A,那麼CAS進行檢查時會發現值沒有發生變化,可是其實是有變化的。ABA問題的解決思路就是在變量前面添加版本號,每次變量更新的時候都把版本號加一,這樣變化過程就從「A-B-A」變成了「1A-2B-3A」。優化
循環時間長開銷大:CAS操做若是長時間不成功,會致使其一直自旋,給CPU帶來很是大的開銷。
只能保證一個共享變量的原子操做(JDK1.5以後已有解決方案):對一個共享變量執行操做時,CAS可以保證原子操做,可是對多個共享變量操做時,CAS是沒法保證操做的原子性的。
你們能夠把1和3的解決方案告訴我嗎?
也能夠點擊閱讀原文跳轉。