前置知識面試
知識介紹
- Synchronized簡介:做用、地位、不控制併發的後果
- 兩種用法:對象鎖和類鎖
- 多線程訪問同步方法的7種狀況:是不是static、Synchronized方法等
- Synchronized的性質:可重入、不可中斷
- 原理:加解鎖原理、可重入原理、可見性原理
- Synchronized的缺陷:效率低、不夠靈活、沒法預判是否成功獲取鎖
- 常見問題:
- 如何選擇Lock或Synchronized等
- 如何提升性能、JVM如何解決那個線程獲取鎖等
Synchronized簡介
做用
官方解釋
同步方法支持一種簡單的策略來防止線程干擾和內存一致性錯誤:若是一個對象對多個線程可見,則對該對象變量的全部讀取或寫入都是經過同步方法完成的。編程
通俗易懂的解釋
可以保證在同一時刻最多隻有一個線程執行該段代碼,以達到保證併發安全的效果。安全
地位
- Synchronized是Java的關鍵字,被Java語言原生支持
代碼演示:不使用併發手段的後果演示多線程
代碼實戰:兩個線程同時a++,最後結果會比預計的少併發
![](http://static.javashuo.com/static/loading.gif)
緣由性能
count++,它看上去只是一個操做,實際上包含了三個動做:this
- 讀取count
- 將count加1
- 將count的值寫入到內存中
- 最基本的互斥同步手段
- 併發編程中的元老級角色,是併發編程的必學內容
Synchronized的兩個用法
對象鎖
包括方法鎖(默認鎖對象爲this當前實例對象)和同步代碼塊鎖(本身指定鎖對象)spa
代碼塊形式:手動指定鎖對象線程
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
方法鎖形式:synchronized修飾普通方法,鎖對象默認爲this3d
![](http://static.javashuo.com/static/loading.gif)
類鎖
概念(重要):Java類可能有不少個對象,但只有1個Class對象
本質:因此所謂的類鎖,不過是Class對象的鎖而已
用法和效果:類鎖只能在同一時刻被一個對象擁有
形式1:synchronized加載static方法上
![](http://static.javashuo.com/static/loading.gif)
形式2:synchronized(*.class)代碼塊
![](http://static.javashuo.com/static/loading.gif)
消失的請求解決方案
不使用併發手段會有什麼後果?如何解決?
解決問題
兩個線程同時a++,最後結果會比預計的少
緣由
count++,它看上去知識一個操做,實際上包含了三個動做
- 讀取count
- 將count+1
- 將count的值寫入到內存中
方法一
![](http://static.javashuo.com/static/loading.gif)
方法二
![](http://static.javashuo.com/static/loading.gif)
方法三
![](http://static.javashuo.com/static/loading.gif)
七種常見狀況之123
多線程訪問同步方法的7種狀況
- 兩個線程同時訪問一個對象的同步方法
- 兩個線程訪問的是兩個對象的同步方法
- 兩個線程訪問的是synchronized的靜態方法
- 同時訪問同步方法與非同步方法
- 訪問同一個對象的不一樣的普通同步方法
- 同時訪問靜態synchronized和非靜態synchronized方法
- 方法拋異常後,會釋放鎖
狀況一:
![](http://static.javashuo.com/static/loading.gif)
狀況二:
![](http://static.javashuo.com/static/loading.gif)
狀況三:
![](http://static.javashuo.com/static/loading.gif)
狀況四:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
狀況五:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
狀況六:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
狀況七:
![](http://static.javashuo.com/static/loading.gif)
7種狀況總結
3點核心思想
- 一把鎖只能同時被一個線程獲取,沒有拿到鎖的線程必須等待(對應第一、5種狀況)
- 每一個實例都對應有本身的一把鎖,不一樣實例之間互不影響;例外:鎖對象鎖是*.class以及Synchronized修飾的是static方法的時候,全部對象共用同一把鎖(對應第二、三、四、6種狀況);
- 不管是方法正常執行完畢或者方法拋出異常,都會釋放鎖(對應第7種狀況)
Synchronized缺陷
- 效率低:鎖的釋放狀況少、試圖得到鎖時不能設定超時、不能中斷一個正在試圖得到鎖的線程
- 不夠靈活(讀寫鎖更靈活):加鎖和釋放的時機單一,每一個鎖僅有單一的條件(某個對象),多是不夠的
- 沒法知道是否成功獲取到鎖
![](http://static.javashuo.com/static/loading.gif)
常見面試問題
一、使用注意點:鎖對象不能爲空、做用域不宜過大、避免死鎖
二、如何選擇Lock和Synchronized關鍵字?
三、多線程訪問同步方法的各類具體狀況