Java多線程詳解(七)線程同步機制

線程同步

  • 現實生活中,我們會遇到“同一個資源,多個人都想使用”的問題,比如,食堂排隊打飯,每個人都想喫飯,最天然的解決辦法就是排隊,一個個來。

  • 處理多線程問題時,多個線程訪問同一個對象,並且某些線程還想修改這個對象,這是我們就需要用到線程同步。線程同步其實就是一種等待機制,多個需要同時訪問此對象的線程進入這個對象的等待池形成隊列,等待前面的線程使用完畢,下一個線程再使用。

形成條件

隊列+鎖

  • 由於統一進程的多個線程共享同一塊存儲空間,在帶來方便的同時,也帶來了訪問衝突問題,爲了保證數據在方法中被訪問時的正確性,在訪問時加入鎖機制synchronized,當一個線程獲得對象的排它鎖,獨佔資源,其他線程必須等待,使用後釋放鎖即可,存在以下問題:
    • 一個線程持有鎖會導致其他所有需要此鎖的線程掛起
    • 在多線程競爭下,加鎖,釋放鎖會導致比較多的上下文切換和調度延遲,引起性能問題
    • 如果一個優先級高的線程等待一個優先級低的線程會釋放鎖,會導致優先級倒置,引起性能問題

同步方法

  • 由於我們可以通過private關鍵字來保證數據對象只能被方法訪問,所以我們只需要針對方法提出一套機制,這套機制就是synchronized關鍵字,它包括兩種用法:synchronized方法和synchronized塊
//同步方法
public synchronized void method(int args){}
  • synchronized方法控制“對象”的訪問,每個對象對應一把鎖,每個synchronized方法都必須獲得調用該方法的對象的鎖才能執行,否則線程會阻塞,方法一旦執行,就獨佔該鎖,直到該方法返回才釋放鎖,後面被阻塞的線程才能獲得和這個鎖,繼續執行。缺陷:若將一個大的方法申明爲synchronized將會影響效率

同步塊

  • 同步塊:synchronized(Obj){}
  • Obj稱之爲同步監視器
    • Obj可以是任何對象,但是推薦使用共享資源作爲同步監視器
    • 同步方法中無需指定同步監視器,因爲同步方法的同步監視器就是this,就是這個對象本身,或者是class【反射】
  • 同步監視器的執行過程
  1. 第一個線程訪問,鎖定同步監視器,執行其中代碼
  2. 第二個線程訪問,發現同步監視器被鎖定,無法訪問
  3. 第一個線程訪問完畢,解鎖同步監視器
  4. 第二個線程訪問,發現同步監視器沒有鎖,然後鎖定並訪問
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章