- 線程安全
- 什么是synchronized關鍵字?
- synchronized實現方式
- 1.修飾實例方法
- 2.修飾靜態方法
- 3.修飾代碼塊
- synchronized關鍵字底層原理
- synchronized修飾實例方法
- monitor鎖是什么?
- Java對象內存布局
- synchronized修飾代碼塊
- 鎖優化
- 自旋鎖
- 鎖粗化
- 鎖消除
- 鎖膨脹
- synchronized關鍵字實現單例模式
- synchronized 和 volatile 的區別?
- 尾語
- 參考資料:
前言
今天我們來聊聊synchronized關鍵字,其可以同時保證三者,實現線程安全。
線程安全
在介紹synchronized關鍵字
之前,我們得強調一下什么是線程安全,所謂線程安全:
當多個線程同時訪問一個對象時, 如果不用考慮這些線程在運行時環境下的調度和交替執行, 也不需要進行額外的同步, 或者在調用方進行任何其他的協調操作, 調用這個對象的行為都可以獲得正確的結果, 那就稱這個對象是線程安全的 。
什么是synchronized關鍵字?
在 Java 早期版本中,synchronized 屬于 重量級鎖 ,效率低下;不過在 Java 6 之后,Java 官方對從 JVM 層面對 synchronized 較大優化,所以現在的 synchronized 鎖效率也優化得非常不錯。目前不論是各種開源框架還是 JDK 源碼都大量使用了 synchronized 關鍵字
synchronized實現方式
synchronized
的使用其實比較簡單,可以用它來修飾實例方法和靜態方法,也可以用來修飾代碼塊。我們需要注意的是synchronized
是一個對象鎖,也就是它鎖的是一個對象。我們無論使用哪一種方法,synchronized
都需要有一個鎖對象
- 修飾實例方法
- 修飾靜態方法
- 修飾代碼塊
1.修飾實例方法
synchronized修飾實例方法, 在方法上加上synchronized關鍵字即可。
public class SynchronizedTest1 {
public synchronized void test() {
System.out.println("synchronized 修飾 方法");
}
}
此時,synchronized加鎖的對象就是這個方法所在實例的本身,作用于當前實例加鎖,進入同步代碼前要獲得 當前實例的鎖 。
補充一個常見的面試題:構造方法可以用synchronized關鍵字修飾嗎?
不能,也不需要,因為構造方法本身就是線程安全的
2.修飾靜態方法
synchronized修飾靜態方法的使用與實例方法并無差別,在靜態方法上加上synchronized關鍵字即可
public static synchronized void test(){
i++;
}
由于靜態方法不屬于任何一個實例對象,歸整個類所有,不依賴于類的特定實例,被類的所有實例共享。給靜態方法加synchronized
鎖,會作用于類的所有對象實例 ,進入同步代碼前要獲得 當前靜態方法所在類的Class對象的鎖 。
有一點我們需要知道:如果一個線程 A 調用一個實例對象的非靜態 synchronized 方法,而線程 B 需要調用這個實例對象所屬類的靜態 synchronized 方法,是允許的,不會發生互斥現象, 因為訪問靜態 synchronized 方法占用的鎖是當前類的鎖,而訪問非靜態 synchronized 方法占用的鎖是當前實例對象鎖 。
3.修飾代碼塊
synchronized修飾代碼塊需要傳入一個對象。
public class SynchronizedTest2 {
public void test() {
synchronized (this) {
System.out.println("synchronized 修飾 代碼塊");
}
}
}
此時synchronized加鎖對象即為傳入的這個對象實例,指定加鎖對象,進入同步代碼庫前要獲得給定對象的鎖 需要注意的是這里的**this **:
- synchronized(object) ,表示進入同步代碼庫前要獲得 給定對象的鎖
- synchronized(類.class) ,表示進入同步代碼前要獲得 給定 Class 的鎖
- 最好不要使用 synchronized(String a) ,因為在 JVM 中,字符串常量池具有緩存功能, 如果我們多次加鎖,會加鎖在同一個對象上
-
JAVA
+關注
關注
19文章
2966瀏覽量
104704 -
代碼
+關注
關注
30文章
4780瀏覽量
68530 -
線程安全
+關注
關注
0文章
13瀏覽量
2458
發布評論請先 登錄
相關推薦
評論