類鎖和對象鎖

目前我理解的synchronized鎖分爲對象鎖和類鎖

對象鎖 
例如
class C {
    public synchronized void aa() {
        System.out.println("aa method");
        try {
            Thread.sleep(10000);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void bb() {
        System.out.print("bb method");
    }
}
這就是 對象鎖  當同一個對象 在不同線程調用方法的時候 會串行的訪問  例如 線程1訪問完aa 線程b才能訪問  (這是一種情況,)第二種線程1在執行aa  線程2也不能執行bb() 因爲對象鎖被線程1持有。 如果在兩個線程中的對象不是同一個實例那麼無論如何都不會引起阻塞。因爲他們是持有了不同的對象鎖。
下面是例子:
public class ThreadTest {
    private static final new C();

    public static void main(final String[] args) {

        new Thread(new Runnable() {
            @Override public void run() {
                c.aa();
            }
        }).start();
        new Thread(new Runnable() {
            @Override public void run() {
                c.bb();
            }
        }).start();
    }
}

class C {
    public synchronized void aa() {
        System.out.println("aa method");
        try {
            Thread.sleep(10000);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void bb() {
        System.out.print("bb method");
    }
}
兩個線程都持有一個對象c,那麼無論誰先執行,當一個線程執行的時候,另一個線程註定不能進入同一個同步方法,因爲對象鎖被佔有了。這裏可以把鎖看成一種資源。
下面是類鎖,首先說說什麼樣的是類鎖,我理解的是 只要是像synchronized(XXX.class) 或者是靜態的同步方法,那麼線程進入到這些區域的時候就會先獲得類鎖。類鎖也是一種稀缺的資源,
當一個線程獲得了一個類鎖後,那麼其他線程就不能夠進入到(需要這把類鎖才能進入的方法和同步塊中)例如兩個線程,分別叫線程1和線程2 ,當線程1調用一個靜態同步方法的時候,另一個線程2不能調用這個方法,或者這個類的其他靜態同步方法。但是非靜態的同步方法是不會被阻塞的,因爲 兩者的鎖不相同,一個是類鎖,一個是對象鎖。
下面是代碼示例:
public class ThreadTest1 {

    public static void main(final String[] args) {
        final ThreadA threadA = new ThreadA();
        threadA.setName("A");
        threadA.start();

        final ThreadB threadB = new ThreadB();
        threadB.setName("B");
        threadB.start();

    }
}

class Service {
    public void printA() {
        synchronized (Service.class) {

            System.out.println("線程" + Thread.currentThread().getName() + "進入printA");
            System.out.println(Thread.currentThread().getName());
            try {
                Thread.sleep(10000);
            } catch (final InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("線程" + Thread.currentThread().getName() + "離開printA");
        }
    }

    public void printB() {
        synchronized (Service.class) {
            System.out.println("線程" + Thread.currentThread().getName() + "進入printB");
            System.out.println(Thread.currentThread().getName());
            System.out.println("線程" + Thread.currentThread().getName() + "離開printB");
        }
    }
}

class ThreadA extends Thread {
    @Override public void run() {
        new Service().printA();
    }
}

class ThreadB extends Thread {
    @Override public void run() {
        new Service().printB();
    }
}
當線程1進入到printA()當中的時候,會陷入睡眠10秒,這時候會發現線程2無法執行printB()方法,(這是再線程1先搶到了類鎖的情況下),因爲線程2要想調用PrintB()它要先獲得類鎖,而類鎖被線程1佔用。這樣線程1就把線程2阻塞了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章