前言
在平常的開發中我們處理對象及變量的并發訪問(保證數據的線程性安全)時都會想到synchronized
關鍵字。當然碰到些具體實例還有其他選擇用于保證多線程訪問資源的同步性,例如:ReentrantLock
、ReentrantReadWriteLock
。
synchronized的使用
我們首先來了解下什么對象鎖,什么是類鎖?對象鎖是用于對象實例方法,或者一個對象實例上的,類鎖是用于類的靜態方法或者一個類的class對象上的
-
sychronized
關鍵字添加到static
靜態方法上或synchonized(Class)
代碼塊是給Class類上鎖 -
sychronized
關鍵字添加到非static
靜態方法上是給對象上鎖
從以上兩點的定義上可能理解起來有些吃力,下邊我們通過幾個demon來驗證下。
public class Service {
synchronized public static void methodA() {
try {
System.out.println("methodA start by " + Thread.currentThread().getName()+" at time " + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("methodA end by " + Thread.currentThread().getName()+" at time " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public static void methodB() {
try {
System.out.println("methodB start by " + Thread.currentThread().getName() +" at time " + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("methodB end by " + Thread.currentThread().getName()+" at time " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public void methodC() {
try {
System.out.println("methodC start by " + Thread.currentThread().getName()+" at time " + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("methodC end by " + Thread.currentThread().getName()+" at time " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Test實例
運行Test實例結果
我們來分析下運行結果:methodA
methodC
兩線程交叉(異步)執行,故此我們有這樣的一個結論這兩個線程分別搶占的是不同的鎖一個是類鎖(methodA),一個是對象鎖(methodC)。更深層次的說明了類鎖和對象鎖是兩個不一樣的鎖,控制著不同的區域,它們是互不干擾的。同樣,線程獲得對象鎖的同時,也可以獲得該類鎖,即同時獲得兩個鎖,這是允許的.
methodA
與methodB
都是搶占同一個類鎖,這兩線程的運行結果符合預期的同步執行。
末尾
三人行,必有我師。最近都進行多線程以及高并發這塊的掃盲,在給大家分享干貨的同時,才疏學淺還望大家大刀予以斧正。也歡迎關注我的掘金或簡書,名稱為柴碼