1. 程式人生 > >java中的類鎖和物件鎖對比分析

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關鍵字修飾的方法,已經從物件級別上升到類級別了,所以,不論多少物件,都共有這個方法,所以才出現這種不論多少物件都會執行緒等待的現象。