Java鎖機制 synchronized 詳解

來源:互聯網
上載者:User

Java鎖機制 synchronized 詳解

進行多線程編程的時候,需要考慮的是線程間的同步問題。對於共用的資源,需要進行互斥的訪問。在Java中可以使用一些手段來達到線程同步的目的:

1. synchronized

2. ThreadLocal,執行緒區域變數

3. Java.util.concurrent.Lock

Java中,線程會共用堆上的執行個體變數以及方法區的類變數,而棧上的資料是私人的,不必進行保護。synchronized方法或synchronized塊將標記一塊監視地區,線程在進入該地區時,需要獲得對象鎖或類鎖,JVM將自動上鎖。在這裡,我們將探討synchronized使用時的三種情況:

1. 在對象上使用synchronized

2. 在普通成員方法上使用synchronized

3. 在靜態成員方法上使用synchronized

這三種線程同步的表現有何不同?

下面通過三段範例程式碼來示範這三種情況。這裡類比線程報數的情境。

情況一:在普通成員函數上使用synchronized

public class MyThread extends Thread {

    public static void main(String[] args) throws Exception {
        for (int i = 1; i < 100; i++) {
            MyThread t  = new MyThread();
            t.setName("Thread="+i);
            t.start();
            Thread.sleep(100);
        }
    }

    @Override
    public synchronized void run() {
        for (int i = 1; i < 10000; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

對一個成員函數使用synchronized進行加鎖,所擷取的鎖,是方法所在對象本身的對象鎖。在這裡,每個線程都以自身的對象作為對象鎖,要對線程進行同步,要求鎖對象必須唯一,所以這裡多個線程間同步失敗。

情況二:在對象上使用synchronized

這裡在類中增加一個成員變數lock,在該變數上使用synchronized:

public class MyThread1 extends Thread {

    private String lock;

    public MyThread1(String lock) {
        this.lock = lock;
    }

    public static void main(String[] args) throws Exception {
        String lock = new String("lock");
        for (int i = 1; i < 100; i++) {
            Thread t = new MyThread1(lock);
            t.setName("Thread=" + i);
            t.start();
            Thread.sleep(100);
        }
    }

    @Override
    public void run() {
        synchronized (lock) {
            for (int i = 1; i < 10000; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

100個線程在建立的時候,都傳遞了同一個lock對象(在main中建立的)去初始化線程類成員lock,因此,這100個線程都在同一個lock對象上進行synchronized同步。因此線程同步成功。

情況三:在靜態成員函數上使用synchronized

public class MyThread2 extends Thread {


    public static void main(String[] args) throws Exception {

        for (int i = 1; i < 10; i++) {
            Thread t = new MyThread2();
            t.setName("Thread=" + i);
            t.start();
            Thread.sleep(10);
        }
    }

    public static synchronized void func() {
        for (int i = 1; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }

    @Override
    public void run() {
        func();
    }
}

這種情況下,線程獲得的鎖是對象鎖,而對象鎖是唯一的,因此多個進程間也能同步成功。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.