死鎖
- 多個線程一起佔有共享資源,並且都在等待其他線程釋放資源,你等我,我等你,某一個同步塊同時擁有
兩個以上對象的鎖
時,就可能會發生死鎖問題。 - 產生死鎖的必要條件:
- 互斥條件:一個資源每次只能被一個進程使用。
- 請求和保持條件:一個進程因請求資源而阻塞時,對方獲得的資源保持不放。
- 不剝奪條件:進程已獲得資源,在未使用完之前,不能強行剝奪。
- 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關係。
- 我們只要想辦法破壞其中一個條件就可以避免死鎖。
Lock鎖
- JDK1.5之後出來,提供了更強大的線程同步機制—通過顯示定義同步鎖對象來實現同步,同步鎖使用
Lock
對象充當。 java.util.concurrent.locks.lock
接口是控制多個線程對共享資源進行訪問的工具。鎖提供了對共享資源的獨佔訪問,每次只能有一個線程對Lock
對象加鎖,線程開始訪問共享資源之前要先獲得Lock
對象。ReentrantLock
類實現了Lock
,他擁有與synchronized
相同的併發性和內存語義,在實現線程安全控制中,比較常用的是ReentrantLock
可以顯示的加鎖,釋放鎖。
synchronized與lock的區別
Lock
是顯示鎖(手動開啓和關閉鎖,別忘記關閉鎖)synchronized
是隱式鎖,出了作用域自動釋放。Lock
只有代碼快鎖,synchronized
有代碼塊鎖和方法鎖。- 使用
Lock
鎖,JVM將花費較少的時間來調度線程,性能更好,並且具有更好的擴展性(提供更多的子類) - 優先使用順序:
Lock
----同步代碼塊(已經進入了方法體,分配了相應資源)----同步方法(在方法體之外)
生產者消費者問題
- 生產者和消費者共享同一個資源,二者之間互相依賴。互爲條件。
- 對於生產者,沒有生產產品之前,要通知消費者等待,生產好了之後,要立馬通知消費者來取,
- 對於消費者,在消費之後,要通知生產者已經結束消費,需要生產新的產品以供消費。
- 在生產者消費者問題中,僅僅有synchronized是不夠的
synchronized
可阻止併發更新同一個共享資源,實現了同步。
synchronized
不能用來實現不同線程之間的消息傳遞(通信)
管程法
信號燈法
線程池
- 經常創建和銷燬的,使用量特別大的資源,比如併發情況下的線程,對性能影響很大,
- 提前創建好多個線程,放入線程池中,使用時直接獲取,使用完放回池中,可以避免頻繁創建和銷燬,實現重複利用,類似生活中的交通工具。
- 使用線程池的好處:
- 提高響應速度(減少了創建線程的時間)。
- 降低資源消耗(重複利用線程池中的線程,不需要每次都創建)
- 便於線程管理:
corePoolSize
:核心池的大小,maximumPoolSize
:最大線程數,KeepAliveTime
:線程沒有任務時,最多保持多長時間後會終止。