線程安全
在多線程條件下,共享狀態(tài)能夠保持正確性。
Synchronized
- 反編譯的時候寥枝,加入了monitorenter和monitorexit指令,實現(xiàn)了同步的語義磁奖。
- monitor是同步的基本組成單元。以前是依靠操作系統(tǒng)的內(nèi)部鎖某筐,在用戶態(tài)和核心態(tài)中轉(zhuǎn)化比搭,是一個重量級的操作。
- 現(xiàn)在的JDK對Monitor做了很多的改進南誊,進行了三種實現(xiàn):
- 沒有競爭時身诺,默認使用偏斜鎖。JVM會利用CAS操作抄囚,在對象頭里的mark word字段里寫入這個線程的ID霉赡,表示對象偏向于這個線程。并不涉及真正的互斥鎖幔托。
- 如果有其他的線程試圖獲取某個已經(jīng)被偏斜過的對象穴亏,JVM需要撤消偏斜鎖蜂挪,并切換到輕量級的鎖實現(xiàn)。同樣利用CAS更改mark word來試圖獲取鎖嗓化。
ReentrantLock
- 一個線程獲取它已經(jīng)獲取的鎖時棠涮,能夠自動成功。這是一個對鎖粒度的概念刺覆,鎖的持有是以線程為單位而不是調(diào)用的次數(shù)严肪。
- 比前者更有定制性,可以響應(yīng)中斷請求谦屑,可以進行超時的鎖獲取驳糯。
- 并發(fā)包里的Condition條件變量,將對線程的wait氢橙,notify操作轉(zhuǎn)化為對對象的操作酝枢,將同步操作轉(zhuǎn)化為對象行為。
ArrayBlockQueue
在使用ReentrantLock類的時充蓝,一定要注意三點:
在finally中釋放鎖隧枫,目的是保證在獲取鎖之后,最終能夠被釋放
不要將獲取鎖的過程寫在try塊內(nèi)谓苟,因為如果在獲取鎖時發(fā)生了異常官脓,異常拋出的同時,也會導(dǎo)致鎖無故被釋放涝焙。
ReentrantLock提供了一個newCondition的方法卑笨,以便用戶在同一鎖的情況下可以根據(jù)不同的情況執(zhí)行等待或喚醒的動作。
f5753a4695fd771f8178120858086811.png
死鎖
所以仑撞,從程序設(shè)計的角度反思赤兴,如果我們賦予一段程序太多的職責,出現(xiàn)“既要…又要…”的情況時隧哮,可能就需要我們審視下設(shè)計思路或目的是否合理了桶良。對于類庫,因為其基礎(chǔ)沮翔、共享的定位陨帆,比應(yīng)用開發(fā)往往更加令人苦惱,需要仔細斟酌之間的平衡采蚀。
- 如果可能的話疲牵,盡量避免使用多個鎖,并且只有需要時才持有鎖榆鼠。否則纲爸,即使是非常精通并發(fā)編程的工程師,也難免會掉進坑里妆够,嵌套的 synchronized 或者 lock 非常容易出問題识啦。
- 如果必須使用多個鎖负蚊,盡量設(shè)計好鎖的獲取順序,這個說起來簡單袁滥,做起來可不容易盖桥,你可以參看著名的銀行家算法
- 使用帶超時的方法,為程序帶來更多可控性题翻。
- 靜態(tài)代碼分析