使用synchronized鎖實作線程同步
為什麼要用線程同步
我們先來看下這段代碼的運作結果:

Java學習交流群:495273252
在多線程上篇部落格已經介紹過了,JVM采用的是搶占式排程模型,當一個線程sleep的時候,其它線程會搶占CPU資源。如果發生在資料庫中,就是“髒讀”。synchronized鎖就是用來解決這個問題的,多線程的線程同步機制實際上是靠鎖的概念來控制的。
第一種方式:synchronized關鍵字修飾函數方法
第二種方式:synchronized關鍵字修飾代碼塊
多個對象多個鎖的情況
三個線程同時進行,每個線程隻列印一個字母,交替列印ABCABC...
prev代表前一個對象,self代表自身。線程先持有前一個對象的鎖和本次要列印的對象的鎖,執行列印,然後喚醒一個正在等待目前對象鎖的線程(剩下的那個線程),并讓它拿到對象鎖。prev.wait()方法讓本線程進入等待狀态,讓本線程休眠,線程自動釋放其占有的對象鎖,并等待notify。如此循環反複列印8次ABC。
總結一下
當多個線程通路同一對象的時候,隻能有一個線程取得對象的鎖,多個對象需要多個對象的鎖。
哪個線程執行了帶synchronized關鍵字的方法,哪個線程就持有該方法所屬對象的鎖,其他的線程要通路這個對象鎖内的内容,都隻能等待這個鎖被釋放後,再去搶占資源獲得對象的鎖。
synchronized修飾非static的方法時,鎖的就是對象本身,也就是this。
synchronized修飾static的方法時,方法中無法使用this,是以它鎖的不是this,而是這個類。是以,static synchronized方法也相當于全局鎖。
使用synchronized關鍵字,應盡量縮小代碼塊的範圍,最好能在代碼塊上加同步,而不是在整個方法上加同步。因為你鎖的範圍大的話,時間又長,别的線程就不會獲得相應的資源。
A線程持有對象的鎖,B線程可以以異步方式調用對象中的非synchronized同步的方法。