1. 同步代碼塊:java
爲了解決併發修改臨界區的問題,Java的多線程支持引入了同步監視器來解決這個問題。使用同步監視器的通用方法就是同步代碼塊。同步代碼塊的語法以下:編程
synchronized(obj){ ...//此處的代碼就是同步代碼塊 }
synchronized後面括號中的obj就是同步監視器。上面代碼的含義:線程開始執行同步代碼塊以前,必須先得到對同步監視器的鎖定。安全
2. 同步方法:多線程
與同步代碼塊對應,Java的多線程安全支持還提供了同步方法,同步方法就是使用synchronized關鍵字來修飾某個方法,則該方法稱爲同步方法。對於同步方法而言,無需顯式指定同步監視器,同步方法的同步監視器是this,也就是該對象自己。併發
3. 釋放同步監視器的鎖定:工具
任何線程進入同步代碼塊、同步方法以前,必須先得到對同步監視器的鎖定,那麼什麼時候會釋放對同步監視器的鎖定呢?程序沒法顯式釋放對同步監視器的鎖定,線程會在以下幾種狀況下釋放對同步監視器的鎖定。this
在以下所示的狀況下,線程不會釋放同步監視器:spa
4. 同步鎖:線程
從Java5開始,Java提供了一種功能更強大的線程同步機制---經過顯式定義同步鎖對象來實現同步。在這種機制下,同步鎖使用Lock對象充當。code
Lock提供了比同步方法和同步代碼塊更普遍的鎖定操做,Lock實現容許更靈活的結構,能夠具備差異很大的屬性,而且支持多個相關的Condition對象。
Lock是控制多個線程對共享資源進行訪問的工具。一般,鎖提供了對共享資源的獨佔訪問,每次只能有一個線程對Lock對象加鎖,線程開始訪問共享資源以前應先得到Lock對象。
某些鎖可能容許對共享資源的併發訪問,如ReadWriteLock。
Lock、ReadWriteLock是Java5 新提供的兩個根接口,併爲Lock提供了ReentrantLock實現類,爲ReadWriteLock提供了ReentrantReadWriteLock實現類。
在實現線程安全的控制中,比較經常使用的是ReentrantLock。使用ReentrantLock對象能夠顯式地加鎖、釋放鎖,一般建議使用finally塊來確保在必要時釋放鎖。
ReentrantLock(可重入鎖)具備可重入性,也就是說,一個線程能夠對已被加鎖的ReentrantLock鎖再次加鎖,ReentrantLock對象會維持一個計數器來追蹤lock()方法的嵌套調用,線程在每次調用lock()加鎖後,必須顯式調用unlock()來釋放鎖,因此一段被鎖保護的代碼能夠調用另外一個被相同鎖保護的方法。
雖然同步方法和同步代碼塊使得多線程安全編程很是方便,但有時須要以更靈活的方式使用鎖。Lock提供了同步方法和同步代碼塊所沒有的其餘功能,包括用於非塊結構的tryLock()方法,以及試圖獲取可中斷鎖的lockInterruptibly()方法,還有獲取超時失效鎖的tryLock(long time,TimeUnit unit)方法。
5. 死鎖: