java中的每個(gè)對(duì)象都可以作為鎖,(不要用String,Integer葵诈,Long),當(dāng)synchrozied 在不同位置祟同,鎖的對(duì)象不一樣:
- 普通同步方法作喘,鎖是當(dāng)前實(shí)例對(duì)象
- 靜態(tài)同步方法,鎖是當(dāng)前類的class對(duì)象
- 同步代碼塊晕城,鎖是括號(hào)中的對(duì)象
在hospot中synchronized是看對(duì)象頭的前2位來判斷是否有鎖泞坦。
- synchronized 是可重入鎖。
程序在執(zhí)行過程中砖顷,如果出現(xiàn)異常贰锁,默認(rèn)情況鎖會(huì)被釋放
- 所以,在并發(fā)處理的過程中滤蝠,有異常要多加小心豌熄,不然可能會(huì)發(fā)生不一致的情況。
- 比如物咳,在一個(gè)web app處理過程中锣险,多個(gè)servlet線程共同訪問同一個(gè)資源,這時(shí)如果異常處理不合適,在第一個(gè)線程中拋出異常芯肤,其他線程就會(huì)進(jìn)入同步代碼區(qū)巷折,有可能會(huì)訪問到異常產(chǎn)生時(shí)的數(shù)據(jù)。 因此要非常小心的處理同步業(yè)務(wù)邏輯中的異常
synchronized的底層實(shí)現(xiàn)
JDK早期的synchronized是 重量級(jí)的 - OS系統(tǒng)鎖
后來改進(jìn):
sync (Object)的時(shí)候崖咨,
一開始 markword 記錄這個(gè)線程ID (偏向鎖)锻拘,如果下次還是當(dāng)前線程來訪問,就可以直接進(jìn)入了击蹲,不用加鎖署拟,提高效率。
如果出現(xiàn)線程爭用:再升級(jí)為 自旋鎖歌豺,這個(gè)過程是占用cpu的芯丧,在用戶態(tài)
自旋10次以后,升級(jí)為重量級(jí)鎖 - OS系統(tǒng)鎖世曾, 內(nèi)核態(tài)缨恒,進(jìn)入等待隊(duì)列,就不占用cpu了
- 執(zhí)行時(shí)間短(加鎖代碼)轮听,線程數(shù)少骗露,用自旋
- 執(zhí)行時(shí)間長,線程數(shù)多血巍,用系統(tǒng)鎖
這個(gè)鎖只能升級(jí)萧锉,不能降級(jí)。