1. 程式人生 > >java多線程(四)

java多線程(四)

控制 clas prev 範圍 交流群 機制 zed 執行 lee

使用synchronized鎖實現線程同步

為什麽要用線程同步

我們先來看下這段代碼的運行結果:

技術分享

技術分享

Java學習交流群:495273252

在多線程上篇博客已經介紹過了,JVM采用的是搶占式調度模型,當一個線程sleep的時候,其它線程會搶占CPU資源。如果發生在數據庫中,就是“臟讀”。synchronized鎖就是用來解決這個問題的,多線程的線程同步機制實際上是靠鎖的概念來控制的。

第一種方式:synchronized關鍵字修飾函數方法

技術分享

Java學習交流群:495273252

第二種方式:synchronized關鍵字修飾代碼塊

技術分享

Java學習交流群:495273252

多個對象多個鎖的情況

三個線程同時進行,每個線程只打印一個字母,交替打印ABCABC...

技術分享

技術分享

技術分享

Java學習交流群:495273252

prev代表前一個對象,self代表自身。線程先持有前一個對象的鎖和本次要打印的對象的鎖,執行打印,然後喚醒一個正在等待當前對象鎖的線程(剩下的那個線程),並讓它拿到對象鎖。prev.wait()方法讓本線程進入等待狀態,讓本線程休眠,線程自動釋放其占有的對象鎖,並等待notify。如此循環反復打印8次ABC。

總結一下

  1. 當多個線程訪問同一對象的時候,只能有一個線程取得對象的鎖,多個對象需要多個對象的鎖。

  2. 哪個線程執行了帶synchronized關鍵字的方法,哪個線程就持有該方法所屬對象的鎖,其他的線程要訪問這個對象鎖內的內容,都只能等待這個鎖被釋放後,再去搶占資源獲得對象的鎖。

  3. synchronized修飾非static的方法時,鎖的就是對象本身,也就是this。

  4. synchronized修飾static的方法時,方法中無法使用this,所以它鎖的不是this,而是這個類。所以,static synchronized方法也相當於全局鎖。

  5. 使用synchronized關鍵字,應盡量縮小代碼塊的範圍,最好能在代碼塊上加同步,而不是在整個方法上加同步。因為你鎖的範圍大的話,時間又長,別的線程就不會獲得相應的資源。

A線程持有對象的鎖,B線程可以以異步方式調用對象中的非synchronized同步的方法。

java多線程(四)