*可重入鎖
*所謂重入鎖,指的是以線程爲單位,當一個線程獲取對象鎖之後,這個線程可以再次獲取本對象上的鎖,而其他的線程是不可以的
*synchronized 和 ReentrantLock 都是可重入鎖
*可重入鎖的意義在於防止死鎖
*實現原理實現是通過爲每個鎖關聯一個請求計數和一個佔有它的線程。
*當計數爲0時,認爲鎖是未被佔有的。線程請求一個未被佔有的鎖時,jvm講記錄鎖的佔有者,並且講請求計數器置爲1 。
*如果同一個線程再次請求這個鎖,計數將遞增;
*每次佔用線程退出同步塊,計數器值將遞減。直到計數器爲0,鎖被釋放。
*
*關於父類和子類的鎖的重入:
*子類覆寫了父類的synchonized方法,然後調用父類中的方法,
*此時如果沒有重入的鎖,那麼這段代碼將產生死鎖。
*
*以下關於子類和父類的到底是幾個對象,也就是影響到父類和子類獲取的是否是同一個鎖(以下解釋來自博客 http://blog.csdn.net/aitangyong/article/details/22695399)
*使用A a = new A()這種方式創建對象的時候,JVM會在後臺給我們分配內存空間,然後調用構造函數執行初始化操作,
*最後返回內存空間的引用。
*即構造函數只是進行初始化,並不負責分配內存空間(創建對象)。
*所以呢其實創建子類對象的時候,JVM會爲子類對象分配內存空間,
*並調用父類的構造函數。
*我們可以這樣理解:創建了一個子類對象的時候,在子類對象內存中,
*有兩份數據,一份繼承自父類,一份來自子類,但是他們屬於同一個對象(子類對象),
*只不過是java語法提供了this和super關鍵字來讓我們能夠按照需要訪問這2份數據而已。
*這樣就產生了子類和父類的概念,但實際上只有子類對象,沒有父類對象。
*
*/
public class LockTest1 extends FLockTest1 implements Runnable{
ReentrantLock lock = new ReentrantLock();
public synchronized void methodA(){
System.out.println(Thread.currentThread().getName()+"this is Method A start" );
//此時訪問
methodB();
System.out.println(Thread.currentThread().getName()+"this is Method A end");
}
public synchronized void methodB(){
System.out.println(Thread.currentThread().getName()+"this is Method B start");
System.out.println(Thread.currentThread().getName()+"this is Method B end");
}
public synchronized void test(){
System.out.println("this is childrenTest started");
super.test();
System.out.println("this is childrenTest end");
}
@Override
public void run() {
//測試本類中的同步方法
methodA();
//測試父類和子類的重入
test();
//測試ReentrantLock
reentrantLockTest1();
}
public static void main(String[] args) {
LockTest1 t1 = new LockTest1();
Thread t = new Thread(t1);
t.start();
t1.methodB();
}
public void reentrantLockTest1(){
lock.lock();
System.out.println("this is reentrantLockTest1");
reentrantLockTest2();
lock.unlock();
}
public void reentrantLockTest2(){
lock.lock();
System.out.println("this is reentrantLockTest2");
lock.unlock();
}
}
class FLockTest1 {
public synchronized void test(){
System.out.println("this is Father Class test started");
System.out.println("this is Father Class test end");
}
}
mainthis is Method B end
Thread-0this is Method A start
Thread-0this is Method B start
Thread-0this is Method B end
Thread-0this is Method A end
this is childrenTest started
this is Father Class test started
this is Father Class test end
this is childrenTest end
this is reentrantLockTest1
this is reentrantLockTest2