java中的類鎖和物件鎖對比分析
說到鎖機制,不得不提到Thread執行緒,而又不得不提到synchronized關鍵字,這個單詞的意思是表示“同步”的意思。用它去修飾方法函式的時候,如果有多個執行緒同時呼叫這個方法函式的時候,那麼當一個執行緒獲得鎖的時候,其他的執行緒只能進入等待佇列,直到這根執行緒執行完畢,釋放鎖的時候,其他執行緒才可以獲得鎖去執行這個方法函式。
這裡我們主要講的是物件鎖和類鎖。物件鎖,顧名思義,即為物件級別的鎖,一個物件一個鎖,不論為這個物件建立多少個執行緒。類鎖,同樣的意思,即為類級別的鎖,一個類一個鎖,這個類的所有物件共有一個鎖。這兩個鎖在形式上的區別是類鎖會有一個static關鍵字修飾。
下面來看看具體的例子,先定義一個具有物件鎖和類鎖的Demo類:
package com.Jevin.thread; public class Demo { //物件鎖: public synchronized void test01(){ try { System.out.println(Thread.currentThread().getName()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } //類鎖: public static synchronized void test02(){ try { System.out.println(Thread.currentThread().getName()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }
我們先建立一個物件兩個執行緒去呼叫物件鎖,觀察一下執行情況:
package com.Jevin.thread; public class ObjectLock { public static void main(String[] args){ //定義一個物件: Demo d=new Demo(); //建立執行緒物件: Thread t1=new Thread(new Runnable() { @Override public void run() { d.test01(); } },"t1"); Thread t2=new Thread(new Runnable() { @Override public void run() { d.test01(); } },"t2"); //啟動執行緒: t1.start(); t2.start(); } }
執行情況:執行緒t1先執行,過了3秒鐘後,執行緒t2再開始執行。那為什麼呢?我的看法是:我們只建立了一個Demo物件,這個在堆中的物件包含了我們的物件鎖的test01方法,兩個執行緒進入同步塊中,符合執行緒的執行規律。
那麼,我們建立兩個物件,會發生什麼現象呢?如下所示:
package com.Jevin.thread;
public class ObjectLock {
public static void main(String[] args){
//定義一個物件:
Demo d1=new Demo();
Demo d2=new Demo();
//建立執行緒物件:
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
d1.test01();
}
},"t1");
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
d2.test01();
}
},"t2");
//啟動執行緒:
t1.start();
t2.start();
}
}
執行結果是:t1執行緒和t2執行緒同時執行,我的看法是:我們建立了兩個物件,這兩個物件各擁有自己的test01方法函式,執行緒t1中的t1引用呼叫自己堆中的物件的test01方法,執行緒t2中的引用t2呼叫自己堆中的test01方法,各自互不影響,所以不會出現執行緒等待那種情況。
那麼,問題來了,我去呼叫有static關鍵字修飾的test02方法,會怎樣呢?答案是,不論一個物件,還是兩個物件,或是n個物件,都會出先執行緒等待,執行緒一個一個的呼叫,為什麼呢?我覺得:有static關鍵字修飾的方法,已經從物件級別上升到類級別了,所以,不論多少物件,都共有這個方法,所以才出現這種不論多少物件都會執行緒等待的現象。