在日常的開發中咱們處理對象及變量的併發訪問(保證數據的線程性安全)時都會想到synchronized
關鍵字。固然碰到些具體實例還有其餘選擇用於保證多線程訪問資源的同步性,例如:ReentrantLock
、ReentrantReadWriteLock
。安全
咱們首先來了解下什麼對象鎖,什麼是類鎖?對象鎖是用於對象實例方法,或者一個對象實例上的,類鎖是用於類的靜態方法或者一個類的class對象上的bash
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實例 併發
咱們來分析下運行結果:methodA
methodC
兩線程交叉(異步)執行,故此咱們有這樣的一個結論這兩個線程分別搶佔的是不一樣的鎖一個是類鎖(methodA),一個是對象鎖(methodC)。更深層次的說明了類鎖和對象鎖是兩個不同的鎖,控制着不一樣的區域,它們是互不干擾的。一樣,線程得到對象鎖的同時,也能夠得到該類鎖,即同時得到兩個鎖,這是容許的.異步
methodA
與methodB
都是搶佔同一個類鎖,這兩線程的運行結果符合預期的同步執行。高併發
三人行,必有我師。最近都進行多線程以及高併發這塊的掃盲,在給你們分享乾貨的同時,才疏學淺還望你們大刀予以斧正。也歡迎關注個人掘金或簡書,名稱爲柴碼
spa